实现点击模型触发事件的思路
在一个3D场景中,事件的交互大部分是点击鼠标完成的,像上图显示的那样,我点击了3号车间,然后与其对应的生产数据框就显示出来了。那么“它”是怎么知道我点击的就是3号车间,这里就用到Three里的一个构造函数“光线投射Raycaster”,Raycaster里的一个方法“setFromCamera”就是从我们场景里的Camera的坐标向我们鼠标点击的方向(这个方向是从2D向3D计算过的,公式统一)发出一条射线,从而获取到这条射线所穿过的模型数组,进而获取到具体是哪个模型(数组里的第一个)。这里可能有疑问,我怎么知道获取到的模型就是3号车间并于3号车间的生产数据关联起来的?我的思路就是导入模型时,将唯一识别字段放进模型数据里面去,我用的是“name”字段,然后Raycaster获取到模型数据在对比一下“name”就获取到了3号车间的生产数据。
实现点击模型触发事件的代码实施
因为我用的是Vue框架,所以就用Vue的格式顺序介绍。
首先是data里面存放两个对象:
//用于点击事件
raycaster: new THREE.Raycaster(),
mouse: new THREE.Vector2(),
然后methods里向容器添加点击监听事件:
this.container.addEventListener('click', this.onMouseClick, false);
然后methods里针对监听事件编写具体逻辑:
onMouseClick(event) {
this.dialogControl = {
show: false,
top: 0,
left: 0
};
// 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
this.mouse.x = (event.clientX / this.container.clientWidth) * 2 - 1;
this.mouse.y = -(event.clientY / this.container.clientHeight) * 2 + 1;
this.raycaster.setFromCamera(this.mouse, this.camera);
// 计算物体和射线的焦点
let intersects = this.raycaster.intersectObjects(this.scene.children, true);
// 获取选中最近的 Mesh 对象
if (intersects.length !== 0 && intersects[0].object instanceof THREE.Mesh) {
let selectName = intersects[0].object.name;
this.houseData.forEach(h => {
if (h.id === selectName) {
this.dialogData = h;
this.dialogControl = {
show: true,
top: event.clientY,
left: event.clientX
};
}
});
}
},
完成以上代码就完成了交互,其中上文中的houseData、dialogData、dialogControl是我自己代码里的需求,可以不做参考。
{{ cmt.username }}
{{ cmt.content }}
{{ cmt.commentDate | formatDate('YYYY.MM.DD hh:mm') }}