在高德地图实现流动的线图层

介绍

有朋友反馈说最近分享的内容不太好理解,那么今天来分享个早前开发的图层制作过程,基于GIS数据代码生成流动的车行线,上手很简单。下面我将在实现思路、具体开发、数据来源这几方面逐步讲解,希望读者能从中获取对数据可视化开发的兴趣。文中使用到高德地图JSAPI、three.js和一些GIS数据处理工具。

实现思路

  1. 这是我们通常能够获取到的数据,从geoJSON数据通常没有真正的曲线,得到通常是基于关键节点生成的线段几何体,只要线越密集,看上去就越平滑,所消耗的资源也就越多。

  2. 在空间几何中,线本身是没有宽度这个概念的,我们能看到不同粗细程度到线,其本质其实是一连串拼合的三角面带,这些面始终朝着相机,这样的话才保证我们在不同角度看到的始终是"均匀圆润"的线。

  3. 给这些几何赋予纯色材质,整条线看着像一个整体。

  4. 根据具体场景给几何体赋予贴图,我们知道如果用相机长曝光模式去拍摄夜晚车辆移动,能够看到一条从亮到暗的轨迹,因为给线图层也赋予这样一层贴图。

  5. 通过调整贴图的X轴偏移让线条动起来。

  6. 增加后期辉光效果,给图层赋予光的质感。

实现步骤

  1. 编写构造函数,声明基础的参数。这里Layer为基类,封装了在高德地图上创建glCustomLayer图,管理图层,逐帧函数等基础操作。

    jsx 复制代码
    class FlowlineLayer extends Layer {
      // 图层数据
            _data = []
            // 线材质
      _material = null
    
      /**
       *  @param {Object}   config
       *  @param {geoJSON}  config.data 路径数据  
       *  @param {Number}   [config.lineWidth=20.0] 路径线条宽度
       *  @param {Number}   [config.altitude=0.0] 整体海拔高度
       *  @param {Array}    [config.zooms=[5,14]] 显示区间
       *  @param {Boolean}  [config.animate=true] 是否显示动画
       *  @param {Number}   [config.speed=1.0]  流动速度系数
       *  @param {String}   [config.uvMapURL='./static/texture/road_bg1.png'] 线条纹理URL
       */
      constructor (config) {
        const conf = {
          data: null,
          speed: 1,
          animate: true,
          lineWidth: 20.0,
          altitude: 0.0,
          uvMapURL: './static/texture/road_bg1.png',
          ...config
        }
    
        super(conf)
    
        this.initData(conf.data)
      }	
    }
  2. 将Polyline的geoJSON数据并转为空间坐标

    jsx 复制代码
    initData (data) {
      const arr = data?.features.map(item => {
        return item?.geometry?.coordinates[0]
      })
    	// 经纬度转为空间坐标
      const res = this.customCoords.lngLatsToCoords(arr)
      this._data = res
    }
  3. 根据数据创建几何体,并设置材质。事实上我们得到的是一条没有宽度的线的数据,而最终的展示的是平行于地面的一条平面带,这里我们使用插件meshline,它提供的MeshLineGeometry能够自动帮我们生成所需的几何体。

    jsx 复制代码
    import { MeshLineGeometry, MeshLineMaterial } from '../plugins/meshline.js'
    //...
    
    initLines () {
        const { scene } = this
    
    	  //材质纹理
        const texture = new THREE.TextureLoader().load(this.mergeSourceURL(this._conf.uvMapURL))
        texture.wrapS = THREE.RepeatWrapping
        texture.wrapT = THREE.RepeatWrapping
        const material = new MeshLineMaterial({
          lineWidth: this._conf.lineWidth,
          sizeAttenuation: 1,
          useMap: 1,
          opacity: 1,
          map: texture,
          transparent: true,
          depthTest: true
        })
        this._material = material
    
    	  //生成网格体
        const multiLine = [...this._data]
        multiLine.forEach(lineData => {
          const points = []
          lineData.forEach(([x, y]) => {
            points.push(new THREE.Vector3(x, y, this._conf.altitude))
          })
    
          const line = new MeshLineGeometry()
          line.setPoints(points)
          const mesh = new THREE.Mesh(line, material)
    
          scene.add(mesh)
        })
      }
  4. 在requestAnimationFrame逐帧修改纹理的x偏移量,形成动画效果

    jsx 复制代码
    // 更新纹理偏移量
    update () {
        if (!this._isAnimate) {
          return
        }
        if (this._material?.uniforms?.offset) {
          this._material.uniforms.offset.value.x -= 0.01 * this._conf.speed
        }
    }
  5. 添加后期效果,这块不作展开,有兴趣可以看 这里

    jsx 复制代码
    const layer = new FlowlineLayer({
        id: 'trafficLayer',
        //...
      })
    
      layer.on('complete',(layer)=>{
        new EffectLayer({
            layer,
            style:{
                strength: 1.0, //发光强度
                radius: 0.5 //泛光半径
            }
        })
      })

路径数据从哪来

  1. 通过地图引擎的路径导航功能获取路径,如下图所示,通过指定起点、终点、经过点可以从API中获取规划好的路径数据,适合在地图上能查得到的部分道路

  2. 自行绘制,如果需要展示的路径还处于规划中,或者属于园区内部道路数据,在官方地图上无法获取,则需要人工使用工具做绘制,这里推荐使用QGIS绘制矢量图层。

  3. 如果是涉及范围或数据量较大的路径,则需要通过某些途径导出了,通过OSM可以无套路导出所需的各种点线面数据,缺点就是有些数据实在太老旧了。在国内我们使用水经注之类的GIS数据下载器获取最新最全的数据,当然,优质的数据都是收费的。

相关链接

生成带宽度的线-MeshLine的使用

开放且免费的地理信息系统OSM

相关推荐
杨超越luckly1 天前
HTML应用指南:利用GET请求获取中国生活垃圾焚烧发电厂位置信息
python·arcgis·html·数据可视化·生活垃圾焚烧发电厂
柳杉2 天前
Three.js × Blender:从建模到 Web 3D 的完整工作流深度解析
前端·javascript·数据可视化
Highcharts.js3 天前
在React中使用图表库时,优先选择组件化方案可以降低开发复杂度
前端·javascript·react.js·数据可视化·highcharts
数据科学小丫3 天前
Power BI 使用
数据分析·数据可视化·powerbi
极光代码工作室4 天前
基于Hadoop的日志数据分析系统设计
大数据·hadoop·python·数据分析·数据可视化
一颗烂土豆7 天前
拒绝 rem 计算!Vue3 大屏适配,我用 vfit 一行代码搞定
vue.js·响应式设计·数据可视化
技术民工之路7 天前
Gephi网络(图)分析与可视化工具
大数据·数据可视化
爱学习的程序媛8 天前
【Web前端】蚂蚁AntV:企业级数据可视化全栈方案
前端·信息可视化·前端框架·web·数据可视化
数字冰雹8 天前
数字孪生携手AIGC:一个指令,一座智慧城市的全景智能即刻生成
人工智能·ai·aigc·智慧城市·数字孪生·数据可视化
ayingmeizi1639 天前
从算力领先到增长领先:前沿科技企业为何需要AI原生CRM作为增长引擎
人工智能·科技·数据可视化·crm·ai-native