百度地图 - MapVGL中使用three.js

3,778 阅读3分钟

这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战

简介

在使用MapVGL进行数据可视化展示数据时,发现了ThreeLayer图层,深入了解后发现它非常的强大。以前听到产品说要在地图上使用模型,第一反应就是这玩意我好想做不了。了解ThreeLayer后,使用模型也不是不可以,不过的加钱,嘿嘿。下面我们就开始深入了解它。

ThreeLayer

  1. MapVGL中的一个图层,继承自 Layer
  2. 可以把Threejs开发的模型放入ThreeLayer图层中,通过MapVGL加入百度地图上。
  3. 要使用ThreeLayer图层,需要额外引入mapvgl.threelayers包。
<script src="https://unpkg.com/mapvgl/dist/mapvgl.threelayers.min.js"></script>
<script src="https://code.bdstatic.com/npm/mapvgl@1.0.0-beta.130/dist/mapvgl.threelayers.min.js"></script>
  1. 为了方便我们使用Threejs。其内部已内置了three.js不需要在再次引入three.js。 通过以下方法使用:
var THREE = mapvgl.THREE;

方法

  • add(obj, point?) 第一个参数为Threejs对象,第二个为坐标,非必传。需注意不传第二个参数Threejs对象的坐标需要自己定义。Threejs对象的position属性坐标和地图点坐标是有区别。
  • remove(obj) 参数为Threejs对象。移除ThreeLayer中的Threejs对象。

开始使用

  • 通过<script>标签引入地图api地址和mapvgl地址,这里的ak是你在地图服务中心注册的。不了解的可以点 这里
<script src="https://api.map.baidu.com/api?type=webgl&v=1.0&ak=?"></script>
<script src="https://unpkg.com/mapvgl/dist/mapvgl.min.js"></script>
<script src="https://unpkg.com/mapvgl/dist/mapvgl.threelayers.min.js"></script>
  • 初始化地图。
      // 百度地图API功能
      var map = new BMapGL.Map('bmap') // 创建Map实例
      // 初始化地图,设置中心点坐标和地图级别
      map.centerAndZoom(new BMapGL.Point(116.403928, 39.914972), 13)
      // 启用 鼠标滚轮事件
      map.enableScrollWheelZoom()
  • 初始化MapVGL,创建ThreeLayer图层并加入图层管理器中。
      var view = new mapvgl.View({
        map: map
      })
      // 创建 three.js 图层
      var threeLayer = new mapvgl.ThreeLayer()
      view.addLayer(threeLayer)
      // 实例化three.js
      var THREE = mapvgl.THREE
      // 坐标装换
      var projection = mapvgl.MercatorProjection
      var point = projection.convertLL2MC(new BMapGL.Point(116.403928, 39.914972))
      var point2 = projection.convertLL2MC(new BMapGL.Point(116.493928, 39.914972))
    
      // 球体网格模型
      var geometry = new THREE.SphereGeometry(160, 140, 140)
      var material = new THREE.MeshBasicMaterial({ color: 0xff0000, flatShading: true, wireframe: false })
      var cube = new THREE.Mesh(geometry, material)
      cube.position.x = point.lng
      cube.position.y = point.lat
      cube.position.z = 20
      threeLayer.add(cube)
      
      // 球体网格模型
      var geometry2 = new THREE.SphereGeometry(160, 140, 140)
      var material2 = new THREE.MeshBasicMaterial({ color: 0xff0000 })
      var cube2 = new THREE.Mesh(geometry2, material2)
      // cube2.position.x = point2.lng
      // cube2.position.y = point2.lat
      cube2.position.z = 20
      threeLayer.add(cube2, point2)

1.gif

  1. 我们使用three.js创建好模型后是直接放入ThreeLayer图层。我们不需要关心three.js中的场景、相机、光线等,在图层中已创建好。
  2. 要想通过地理坐标展示到地图上,需要使用mapvgl.MercatorProjection转换坐标为3d坐标。
  3. 通过add()加入模型时,两种传值方式是有区别的。具体使用那种方式可以根据业务来判断。
  • 第一种,直接给模型设置3d坐标,使用add()时不传第二个参数,加入的模型是根据地图来控制的,地图放大缩小,模型也会有相应的变化。
  • 第二种,通过add()传入第二个参数设置坐标位置,这时候模型不会根据地图变化而变化,始终保持原有大小。

加入动画

  • three.js中加入动画,是通过渲染器对象,重新绘制修改后的模型。同样的,我们再次调用add(),其内部帮我们调用重绘的方法。
      let x = 0
      let i = 0
      function render() {
        threeLayer.add(cube2, point2)
        i++
        cube2.translateX(x)
        if (i > 100) {
          i = 0
          x = -x
        } else {
          x = x + 0.1
        }
        requestAnimationFrame(render) //请求再次执行渲染函数render
      }
      render()

1.gif