在threejs 在3d地图中绘制css2d地名中,我们给地图添加了css2d标签来标注地名,今天我们在之前的基础上来实现鼠标移入地图高亮,并显示对应区域名称。
效果截图
鼠标移入高亮染效果视频
射线拾取
我们通过射线拾取来获取地图信息,并进行高亮,显示当前区域名称。
/**
* 射线投射器`Raycaster`的射线拾取选中网格模型对象函数choose()
* 选中的网格模型变为半透明效果
*/
var label = tag();
scene.add(label);//标签插入场景中
// console.log(label);
var chooseMesh = null;//标记鼠标拾取到的mesh
function choose(event) {
if (chooseMesh) {
// 把上次选中的mesh设置为原来的颜色
chooseMesh.material[0].color = new THREE.Color(0x064040);
chooseMesh.material[1].color = new THREE.Color(0x064040);
} else {
label.element.style.visibility = 'hidden';//没有选中mesh,隐藏标签
}
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);
// console.log("射线器返回的对象", intersects);
// console.log("射线投射器返回的对象 点point", intersects[0].point);
// console.log("射线投射器的对象 几何体",intersects[0].object.geometry.vertices)
// intersects.length大于0说明,说明选中了模型
if (intersects.length > 0) {
chooseMesh = intersects[0].object;
console.log(chooseMesh)
console.log(intersects[0])
// chooseMesh.material.color.set(new THREE.Color(0xfec308));//选中改变颜色
// 根据鼠标位置设置标签位置(射线与mesh表面相交点世界坐标intersects[0].point)
// intersects[0].point.y += 1;//偏移
chooseMesh.material[0].color = color1;
chooseMesh.material[1].color = color1;
label.position.copy(intersects[0].point);
// console.log(chooseMesh.center)
label.element.innerHTML = chooseMesh.name;
label.element.style.visibility = 'visible';
} else {
chooseMesh = null;
}
}
addEventListener('mousemove', choose); // 监听窗口鼠标滑动事件
演示实例
实例代码下载
项目运行环境 vue3 vite js nodejs 14