function initRay() {
let getBoundingClientRect = canvas.getBoundingClientRect()
// 屏幕坐标转标准设备坐标
let x = ((event.clientX - getBoundingClientRect .left) / canvas.offsetWidth) * 2 - 1;// 标准设备横坐标
let y = -((event.clientY - getBoundingClientRect .top) / canvas.offsetHeight) * 2 + 1;// 标准设备纵坐标
let standardVector = new THREE.Vector3(x, y, 1);// 标准设备坐标
// 标准设备坐标转世界坐标
let worldVector = standardVector.unproject(camera);
// 射线投射方向单位向量(worldVector坐标减相机位置坐标)
let ray = worldVector.sub(camera.position).normalize();
// 创建射线投射器对象
let rayCaster = new THREE.Raycaster(camera.position, ray);
// 返回射线选中的对象 第二个参数如果不填 默认是false
let intersects = rayCaster.intersectObjects(scene.children, true);
if (intersects.length > 0) {
// console.log(intersects[0].object);
}
}
1. getBoundingClientRect():
返回值是一个 DOMRect 对象,这个对象是由该元素的 getClientRects() 方法返回的一组矩形的集合,就是该元素的 CSS 。结果是包含整个元素的最小矩形,具有只读的左、上、右、下、x、y、宽度和高度属性,以像素为单位描述整个边框框。除宽度和高度外的其他属性相对于视口的左上角。
2.event.clientX
clientX 事件属性返回当事件被触发时鼠标指针向对于浏览器页面(或客户区)的水平坐标。客户区指的是当前窗口。
3.offsetWidth
水平方向 width + 左右padding + 左右border-width
4.标准化(归一化)设备坐标NDC
一旦你的顶点坐标已经在顶点着色器中处理过,它们就应该是标准化设备坐标了,标准化设备坐标是一个x、y和z值在 -1.0到1.0 的一小段空间。任何落在范围外的坐标都会被丢弃/裁剪,不会显示在你的屏幕上。下面你会看到我们定义的在标准化设备坐标中的三角形(忽略z轴):
5.Vector3.unproject(camera);
将这个向量从相机的归一化设备坐标(NDC)空间投射到世界空间。