北京市大兴区公交可视化免费开源——持续更新中

声明:本文涉及图文和模型素材仅用于个人学习、研究和欣赏,请勿二次修改、非法传播、转载、出版、商用、及进行其他获利行为。

前言

首先看一下我们要完成的效果图(效果图来自thingjs),大概我们要按照这个来完成。

开发语言

头部组件(HeadTitle)

效果图

地图

首先加载一个地图

js 复制代码
   basemaps: [
      {
        name: "电子地图",
        icon: "img/basemaps/google_vec.png",
        type: "xyz",
        url:
          "https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}",
        show: true,
      },
    ],

效果图的地图是黑色的,需要使用瓦片颜色滤镜GaodeLayer

js 复制代码
  tileLayer = new mars3d.layer.GaodeLayer({
    layer: "vec",
    invertColor: true,
    filterColor: "#485468",
    brightness: 0.6,
    contrast: 1.8,
    gamma: 0.3,
    hue: 1,
    saturation: 0,
  });
  map.addLayer(tileLayer);

效果

北京公交线(OD线)

js 复制代码
//  北京公交线(OD线)
const busLine = () => {
  // 创建矢量数据图层
  graphicLayer = new mars3d.layer.GraphicLayer();
  map.addLayer(graphicLayer);
  let data = bjgjJson;
  let busLines = [];
  data.forEach(function (busLine, idx) {
    let prevPt;
    const points = [];
    for (let i = 0; i < busLine.length; i += 2) {
      let pt = [busLine[i], busLine[i + 1]];
      if (i > 0) {
        pt = [prevPt[0] + pt[0], prevPt[1] + pt[1]];
      }
      prevPt = pt;

      const longitude = pt[0] / 1e4;
      const latitude = pt[1] / 1e4;
      const cart = Cesium.Cartesian3.fromDegrees(longitude, latitude, 100.0);
      points.push(cart);
    }
    busLines.push({
      positions: points,
      style: {
        width: 0.3,
        materialType: mars3d.MaterialType.LineFlow,
        image: getAssetsFile("lightFlow_strip07.png"),
         speed: 2 + 1.0 * Math.random(),
      },
    });
  });

  // 多个线对象的合并渲染。
  const graphic = new mars3d.graphic.PolylineCombine({
    instances: busLines,
  });
  graphicLayer.addGraphic(graphic);
};

北京公交汽车路线和停车点

js 复制代码
const actualBus = () => {
  //处理数据
  busRoute.map(item=>{
    //绘制公交路线
    let positions=item.polyline.split(';')
    let lineData={
      positions,
      style: {
        width: 4,
        color: item.linecolor,
      },
    }
    const BusLine = new mars3d.graphic.PolylinePrimitive(lineData);
    graphicLayer.addGraphic(BusLine);
    //绘制公交停车点
    item.busstops.map(item=>{
      const BusPoints = new mars3d.graphic.PointPrimitive({
        position:item.location,
        style:{
          color: "#fff",
          pixelSize: 5,
          label: {
            text: item.name,
            font_size: 12,
            color: "#19d5ff",
            pixelOffsetY: -20,
            background:true,
            backgroundPadding:8,
            distanceDisplayCondition: true,
            distanceDisplayCondition_far: 5000,
            distanceDisplayCondition_near: 0
          }
        }
      })
      graphicLayer.addGraphic(BusPoints);
    })
  })
};

首先说一下我这个公交线的数据来源高德地图

其中busstops是停车点位,name是公交路线名称,polyline是公交线的经纬度

公交车行驶效果

js 复制代码
const getSampledPositionProperty = (points: any) => {
  let speed = 20;
  let time = 0;
  let startTime = new Date();
  // 公交车的行驶路径
  let busPath = [
    {
      id: 1,
      x: points[0].split(",")[0],
      y: points[0].split(",")[1],
      z: 0,
      time: startTime.toISOString(),
    },
  ];
  // 公交车的发车时间
  for (let i in points) {
    if (i < points.length - 1) {
      let pointFirst = points[i].split(",");
      let pointSecond = points[Number(i) + 1].split(",");
      let positionLeft = Cesium.Cartesian3.fromDegrees(pointFirst[0], pointFirst[1]);
      let positionRight = Cesium.Cartesian3.fromDegrees(pointSecond[0], pointSecond[1]);
      let distance = Cesium.Cartesian3.distance(positionLeft, positionRight);
      time += (distance / 1000 / speed) * 3600;
      let currentTime = parseInt(startTime.getTime() + time * 10000);
      let BusMoment = new Date(currentTime).toISOString();
      let vote = {
        id: i + 2,
        x: pointSecond[0],
        y: pointSecond[1],
        z: 0,
        time: BusMoment,
      };
      busPath.push(vote);
    }
  }
  const property = new Cesium.SampledPositionProperty();
  property.forwardExtrapolationType = Cesium.ExtrapolationType.HOLD;

  let start;
  let stop;
  for (let i = 0, len = busPath.length; i < len; i++) {
    const item = busPath[i];
    const lng = Number(item.x); // 经度
    const lat = Number(item.y); // 纬度
    const height = item.z; // 高度
    const time = item.time; // 时间

    let position = null;
    if (lng && lat) {
      position = Cesium.Cartesian3.fromDegrees(lng, lat, height);
    }
    let juliaDate = null;
    if (time) {
      juliaDate = Cesium.JulianDate.fromIso8601(time);
    }
    if (position && juliaDate) {
      property.addSample(juliaDate, position);
    }

    if (i === 0) {
      start = juliaDate;
    } else if (i === len - 1) {
      stop = juliaDate;
    }
  }

  // 设置时钟属性
  map.clock.startTime = start.clone();
  map.clock.stopTime = stop.clone();
  map.clock.currentTime = start.clone();
  map.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
  map.clock.multiplier = 5;

  if (map.controls.timeline) {
    map.controls.timeline.zoomTo(start, stop);
  }

  // 创建path对象
  let busPosition = new mars3d.graphic.PathEntity({
    position: property,
    orientation: new Cesium.VelocityOrientationProperty(property),
    style: {
      width: 0,
    },
    model: {
      url: "/model/bus.gltf",
      heading: 360,
      fill: true,
      color: "#619e21",
      scale: 1,
      minimumPixelSize: 40,
    },
  });
  graphicLayer.addGraphic(busPosition);
};

给公交车增加车牌号和载客量

js 复制代码
    label: {
      text: busRoute[0].licence + "(" + busRoute[0].passengers + "人)",
      font_size: 12,
      background: true,
      backgroundColor: "#f7bd42",
      outline: true,
      outlineColor: "#fff",
      hasPixelOffset: true,
      pixelOffsetY: -20,
      distanceDisplayCondition: true,
    },

给公交线增加起点和终点

js 复制代码
   if (index === 0) {
        const startingPoint = new mars3d.graphic.BillboardPrimitive({
          position: positions,
          style: {
            image: getAssetsFile("origin.png"),
            scale: 0.7,
            horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
          },
        });
        graphicLayer.addGraphic(startingPoint);
      } else if (index === monomer.busstops.length - 1) {
        const endPoint = new mars3d.graphic.BillboardPrimitive({
          position: positions,
          style: {
            image: getAssetsFile("end.png"),
            scale: 0.7,
            horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
          },
        });
        graphicLayer.addGraphic(endPoint);
      }

项目链接

项目链接

相关推荐
蜗牛快跑21311 分钟前
面向对象编程 vs 函数式编程
前端·函数式编程·面向对象编程
Dread_lxy12 分钟前
vue 依赖注入(Provide、Inject )和混入(mixins)
前端·javascript·vue.js
Leo.yuan27 分钟前
数据量大Excel卡顿严重?选对报表工具提高10倍效率
数据库·数据分析·数据可视化·powerbi
涔溪1 小时前
Ecmascript(ES)标准
前端·elasticsearch·ecmascript
榴莲千丞1 小时前
第8章利用CSS制作导航菜单
前端·css
奔跑草-1 小时前
【前端】深入浅出 - TypeScript 的详细讲解
前端·javascript·react.js·typescript
羡与1 小时前
echarts-gl 3D柱状图配置
前端·javascript·echarts
guokanglun1 小时前
CSS样式实现3D效果
前端·css·3d
咔咔库奇2 小时前
ES6进阶知识一
前端·ecmascript·es6
渗透测试老鸟-九青2 小时前
通过投毒Bingbot索引挖掘必应中的存储型XSS
服务器·前端·javascript·安全·web安全·缓存·xss