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

介绍

有朋友反馈说最近分享的内容不太好理解,那么今天来分享个早前开发的图层制作过程,基于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

相关推荐
邢博士谈科教6 分钟前
比传统机器学习更先进的深度学习神经网络的二分类建模全流程教程
数据挖掘·r语言·数据可视化
GHUIJS4 小时前
【Echarts】vue3打开echarts的正确方式
前端·vue.js·echarts·数据可视化
千汇数据的老司机2 天前
五星级可视化页面(25):非蓝色系,金色系可视化界面。
信息可视化·可视化·数据可视化
B站计算机毕业设计超人2 天前
计算机毕业设计Python知识图谱美团美食推荐系统 美团餐厅推荐系统 美团推荐系统 美食价格预测 美团爬虫 美食数据分析 美食可视化大屏
爬虫·python·深度学习·机器学习·数据分析·数据可视化·推荐算法
Dreams°1232 天前
pyecharts可视化数据大屏【详细教程】
大数据·python·测试工具·信息可视化·数据分析·html·数据可视化
B站计算机毕业设计超人2 天前
计算机毕业设计Python深度学习垃圾邮件分类检测系统 朴素贝叶斯算法 机器学习 人工智能 数据可视化 大数据毕业设计 Python爬虫 知识图谱 文本分类
大数据·人工智能·爬虫·深度学习·算法·机器学习·数据可视化
武艺晴小朋友你好3 天前
基于scRNA-data,运用pySCENIC寻找细胞群里面活跃的调节子
r语言·数据可视化·r语言-4.2.1
安冬的码畜日常3 天前
【D3.js in Action 3 精译_022】3.2 使用 D3 完成数据准备工作
前端·javascript·信息可视化·数据挖掘·数据可视化·d3.js