在之前我们使用echarts绘制的可以下钻的3d地图,vue echarts-gl 3d地图从中国下钻到市级实例,但是echarts-gl绘制出来的3d地图自定义程度不够,我们想要更加灵活的自定义3d地图,所以选择使用threejs来实现3d地图,今天我们来使用threejs来实现地图下钻实例。
3d地图的下钻本质上就是更换地图数据销毁重绘地图。
演示实例
效果截图
地图下钻动画
销毁地图
为了避免内存消耗,我们每次绘制新地图的时候需要先销毁旧地图。
destroyMap() {
var that = this;
if (that.scene) {
that.renderer.setAnimationLoop(null);
function disposeObject(obj) {
if (obj.geometry) {
obj.geometry.dispose();
}
if (obj.material) {
if (Array.isArray(obj.material)) {
obj.material.forEach((material) => {
disposeMaterial(material);
});
} else {
disposeMaterial(obj.material);
}
}
if (obj.texture) {
obj.texture.dispose();
}
}
function disposeMaterial(material) {
if (material.map) {
material.map.dispose();
}
if (material.lightMap) {
material.lightMap.dispose();
}
if (material.bumpMap) {
material.bumpMap.dispose();
}
if (material.normalMap) {
material.normalMap.dispose();
}
if (material.specularMap) {
material.specularMap.dispose();
}
if (material.envMap) {
material.envMap.dispose();
}
if (material.alphaMap) {
material.alphaMap.dispose();
}
if (material.aoMap) {
material.aoMap.dispose();
}
if (material.displacementMap) {
material.displacementMap.dispose();
}
if (material.emissiveMap) {
material.emissiveMap.dispose();
}
if (material.gradientMap) {
material.gradientMap.dispose();
}
if (material.metalnessMap) {
material.metalnessMap.dispose();
}
if (material.roughnessMap) {
material.roughnessMap.dispose();
}
if (material.clearcoatMap) {
material.clearcoatMap.dispose();
}
if (material.clearcoatRoughnessMap) {
material.clearcoatRoughnessMap.dispose();
}
if (material.clearcoatNormalMap) {
material.clearcoatNormalMap.dispose();
}
material.dispose(); // 释放材质
}
while (that.scene.children.length > 0) {
const object = that.scene.children[0];
that.scene.remove(object);
disposeObject(object);
}
that.$refs.map3DMain.innerHTML = ''
that.renderer.dispose(); // 释放 WebGLRenderer 占用的资源
}
}
点击选择地图
我们需要使用射线拾取来获取选中的地图,然后通过这个地图名称去获取地图数据,再进行销毁重绘即可,为了避免重绘地图导致重复注册点击事件,这里我们的点击事件设为1次。
that.chooseMap = function (event) {
var Sx = event.clientX; //鼠标单击位置横坐标
var Sy = event.clientY; //鼠标单击位置纵坐标
//屏幕坐标转WebGL标准设备坐标
var x = (Sx / window.innerWidth) * 2 - 1; //WebGL标准设备横坐标
var y = -(Sy / window.innerHeight) * 2 + 1; //WebGL标准设备纵坐标
//创建一个射线投射器`Raycaster`
var raycaster = new THREE.Raycaster();
//通过鼠标单击位置标准设备坐标和相机参数计算射线投射器`Raycaster`的射线属性.ray
raycaster.setFromCamera(new THREE.Vector2(x, y), camera);
//返回.intersectObjects()参数中射线选中的网格模型对象
// 未选中对象返回空数组[],选中一个数组1个元素,选中两个数组两个元素
var intersects = raycaster.intersectObjects(meshGroup.children);
// intersects.length大于0说明,说明选中了模型
if (intersects.length > 0) {
chooseMesh = intersects[0].object;
if (chooseMesh.name) {
console.log(chooseMesh.name)
if (chooseMesh.name != that.listCode[that.listCode.length - 1].name) {
that.areaName = chooseMesh.name
that.getCode()
}
}
} else {
chooseMesh = null;
}
addEventListener('click', that.chooseMap, {once: true});
}
addEventListener('click', that.chooseMap, {once: true});
实例代码下载
项目运行环境 vue3 vite js nodejs 14