mapbox添加three模型

800 阅读3分钟

添加three模型

需求:在maobox地图上添加模型,并且动态修改模型的位置,大小等。

以下所有代码在vue3项目中所调试的,如果是其它框架或者原生,稍微修改即可。

//1.下载mapbox的包(这里不作重点)
//2.下载Threebox与THREE的包(three这个包可能暂时用不到)

import { Threebox } from 'threebox-plugin';
import * as THREE from 'three';
import mapboxgl, { Map, MapMouseEvent, Point } from 'mapbox-gl';
import {ref,onMounted} from 'vue'

 const mapDom = ref();  // 地图的dom容器
 const glbUrl = 'https://xxxxx.gltf'; // 你的3D模型
 const scale = 0; // 模型的scale
 const options = {	// 将一些属性抽取成为一个对象
    obj: glbUrl,	// 上面定义的模型
    type: 'gltf',	// 模型格式
    scale: { x: scale, y: scale, z: 0 },	// 设置x,y,z轴上的scale大小
    units: 'meters',	// 指定模型的单位长度,这里尺寸单位是米
    rotation: { x: 0, y: 0, z: 0 }, // 旋转角度
  };
  
 let model_Value: any; // 这个后面用来暂存模型的model
 let map; // 地图对象
 let tb: any; // 用来存储three场景的实例
 
  mapboxgl.accessToken =
  'pk.eyJ1Ijoic3o2NjY2NjYiLCJhIjoiY2tuam44NXZzMDEwMzJ1cGV3djR6OHA5cCJ9.2LA3YOPHRLTTB25CvAoIdw';

这些变量定义好后开始添加3D模型和图层

const init = ()=>{
     map = new mapboxgl.Map({
      container: mapDom.value,
      center: [x,y],
      zoom: 14, // 地图起始比列
    });
    
map.on('load',()=>{	// 地图加载完成后执行
      // 创建一个 Three.js 场景的实例
      tb = window.tb = new Threebox(map, map.getCanvas().getContext('webgl'), {
      defaultLights: true, //指定在 Threebox 中是否包含默认的光照设置 ,true表示包含默认光照。
     });
      // 添加3D模型图层
map.addLayer({
      id: 'custom-threebox-model',
      type: 'custom',	// 表示自定义图层,该图层不是 Mapbox 预定义的标准图层类型,而是由开发者自行定义和实现的
      renderingMode: '3d', // 指定了图层的渲染模式。'3d' 表示该图层以三维方式进行渲染
      onAdd:function(){
           // onAdd方法,当图层添加到地图时执行的操作,通常用于初始化图层,在图层首次添加到地图时调用,并且只调用一次
          tb.loadObj(options, (model) => {	// model 为加载完成的 Three.js 模型对象
               //这段代码是在 Threebox 中加载一个对象
               model_Value = model; // 暂存到公共变量上
               model_Value.setRotation({ x: 0, y: 0, z: 0 });	// 旋转角度
               model_Value.setCoords([
               x,	// x,y地图经纬度
               y,
               100,	// 在地图上的高度位置
            ]);
               tb.add(model_Value) // 添加到场景
           })
        },
       render:function(){
            // render 方法定义了地图渲染时图层的更新操作,通常用于更新图层的状态或属性,在每次地图渲染时都会调用
               tb.update();	// 更新场景
        }
      })
   })
}

onMounted(()=>{
    init() // 调用执行
})   

如果不出意外你的模型会成功加载

修改three模型

 // 这里就用mapbox点击事件来模拟,动态修改已加载模型的位置
 // 因为还没有找到可以直接修改这个经纬度的方法,所以我的思路是:
 // + 判断该图层是否存在,如果存在则删除,再重新添加新的该图层和模型
 
 map.on('click',(e)=>{
    const lnglat = [e.lngLat.lng, e.lngLat.lat,200] // 拿到鼠标点击的坐标,以及高度
    // 判断该图层是否存在,不存在则返回undefined
    if (map.getLayer('custom-threebox-model') != undefined) {
         map.removeLayer('custom-threebox-model'); // 删除该图层
         tb.remove(model_Value); // 删除该模型,如果不删除点击后将会添加多个
         // 再重新添加图层和模型
         map.addLayer({
             id: 'custom-threebox-model',
             type: 'custom',
             renderingMode: '3d',
             onAdd: function () {
               tb.loadObj(options, (model) => {
                 model_Value = model;
                 model_Value.setRotation({ x: 0, y: 0, z: 0 });
                 model_Value.setCoords(lnglat);
                 tb.add(model_Value);
               });
             },
             render: function () {
               tb.update();
             },
         });
    }
 })

threejs不太熟,有错误的地方还请大佬指正,还有更好的方法还请大佬指教!

参考mapbox官网案例 docs.mapbox.com/mapbox-gl-j…