前言
上一节通过MeshLine
添加了飞线飞点 这一节把整个场景导入到mapbox中。
思路
主要思路就是mapbox
的customLayer
图层,可以把three
的3d场景通过场景和控制器的重叠进行导入,这样本质上mapbox和three还是两个互不干扰的场景。
实现步骤
- 初始化地图场景
- 当地图加载完成后,初始化custom图层(参考docs.mapbox.com/mapbox-gl-j…
- 设置render中模型位置和相机的相关变化(涉及到坐标转换这个方面准备专门写一章来讲一下自己的理解)
- 其他的three相关内容参考以前的章节
代码
initmap() {
mapboxgl.accessToken =
"??"; //这里请换成自己的token
map = new mapboxgl.Map({
container: "map", // container id 绑定的组件的id
style: "mapbox://styles/mapbox/streets-v11", //地图样式,可以使用官网预定义的样式,也可以自定义
center: [121.47, 31.23], // 初始坐标系
zoom: 15, // starting zoom 地图初始的拉伸比例
pitch: 60, //地图的角度,不写默认是0,取值是0-60度,一般在3D中使用
bearing: -17.6, //地图的初始方向,值是北的逆时针度数,默认是0,即是正北
antialias: true, //抗锯齿,通过false关闭提升性能
});
}
setCustomLayer() {
const customLayer = {
id: "3d-model",
type: "custom",
renderingMode: "3d",
onAdd: this.initThree,
// eslint-disable-next-line no-unused-vars
render: this.threeRender,
};
return customLayer;
},
initThree(map, gl) {
//创建场景
scene = new THREE.Scene();
/**
* 透视投影相机设置
*/
const width = window.innerWidth; // 窗口宽度
const height = window.innerHeight; // 窗口高度
/** 透视投影相机对象 */
camera = new THREE.PerspectiveCamera(60, width / height, 1, 700);
camera.position.set(600, 900, 600); // 树上面观察
camera.lookAt(scene.position); // 设置相机方向(指向的场景对象)
// 创建渲染器对象
// const container = document.getElementById("scene");
renderer = new THREE.WebGLRenderer({
canvas: map.getCanvas(),
context: gl,
antialias: true,
});
// container.appendChild(renderer.domElement); // body元素中插入canvas对象
//创建点光源和环境光源
const point = new THREE.PointLight(0xffffff);
point.position.set(600, 900, 600); // 点光源位置
scene.add(point); // 点光源添加到场景中
// 环境光
const ambient = new THREE.AmbientLight(0x404040, 1);
scene.add(ambient);
renderer.autoClear = false;
// pickingScene = new THREE.Scene(); //离屏渲染
// pickingTexture = new THREE.WebGLRenderTarget(1, 1); //离屏渲染
},
threeRender(gl, matrix) {
const modelOrigin = [121.47, 31.23];
const modelAltitude = 770;
const modelRotate = [Math.PI / 4, 0, 0];
const modelAsMercatorCoordinate = mapboxgl.MercatorCoordinate.fromLngLat(
modelOrigin,
modelAltitude
);
const modelTransform = {
translateX: modelAsMercatorCoordinate.x,
translateY: modelAsMercatorCoordinate.y,
translateZ: modelAsMercatorCoordinate.z,
rotateX: modelRotate[0],
rotateY: modelRotate[1],
rotateZ: modelRotate[2],
scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits(),
};
const rotationX = new THREE.Matrix4().makeRotationAxis(
new THREE.Vector3(1, 0, 0),
modelTransform.rotateX
);
const rotationY = new THREE.Matrix4().makeRotationAxis(
new THREE.Vector3(0, 1, 0),
modelTransform.rotateY
);
const rotationZ = new THREE.Matrix4().makeRotationAxis(
new THREE.Vector3(0, 0, 1),
modelTransform.rotateZ
);
const m = new THREE.Matrix4().fromArray(matrix);
const l = new THREE.Matrix4()
.makeTranslation(
modelTransform.translateX,
modelTransform.translateY,
modelTransform.translateZ
)
.scale(
new THREE.Vector3(
modelTransform.scale,
-modelTransform.scale,
modelTransform.scale
)
)
.multiply(rotationX)
.multiply(rotationY)
.multiply(rotationZ);
camera.projectionMatrix = m.multiply(l);
this.cityanimate();
renderer.resetState();
renderer.render(scene, camera);
map.triggerRepaint();
},
复制代码
调用代码
this.initmap();
map.on("style.load", () => {
let customLayer = this.setCustomLayer();
map.addLayer(customLayer, "waterway-label");
this.addGLTF();
this.creatWall();
this.creatRunLine();
});
复制代码
效果图
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END