添加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…