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

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

前言

首先看一下我们要完成的效果图(效果图来自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);
      }

项目链接

项目链接

相关推荐
ZXT3 分钟前
项目精讲 - keepAlive
vue.js
堕落年代3 分钟前
Vue主流的状态保存框架对比
前端·javascript·vue.js
没资格抱怨5 分钟前
el-pagination的使用说明
javascript·vue.js·elementui
沐千熏10 分钟前
Liunx(CentOS-6-x86_64)使用Nginx部署Vue项目
vue.js·nginx·centos
OpenTiny社区14 分钟前
TinyVue的DatePicker 组件支持日期面板单独使用啦!
前端·vue.js
冴羽14 分钟前
Svelte 最新中文文档教程(22)—— Svelte 5 迁移指南
前端·javascript·svelte
树上有只程序猿18 分钟前
Vue3组件通信:多个实战场景,轻松玩转复杂数据流!
前端·vue.js
剪刀石头布啊26 分钟前
css属性值计算过程
前端·css
bin915331 分钟前
DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加列宽调整功能,示例Table14基础固定表头示例
前端·javascript·vue.js·ecmascript·deepseek
小华同学ai33 分钟前
吊打中文合成!这款开源语音神器效果炸裂,逼真到离谱!
前端·后端·github