郭隆邦老师threejs教程学习笔记
把HTML元素作为模型标签,如果模型位置或相机Camera
参数变化了,需要根据模型新的位置或相机新的参数,重新计算模型标签的屏幕坐标。
OrbitControls改变相机参数
通过相机控件OrbitControls旋转threejs三维场景,本质上改变的是threejs相机对象Camera
的参数。旋转的时候,如果模型在canvas画布上渲染位置改变,模型对应的HTMl元素标签坐标需要跟着改变。
把坐标转换的代码封装为一个函数tag
,可以在threejs周期性执行的渲染函数render中周期性执行函数tag()
,也可以模型或相机发生变化的时候调用tag
函数重新计算坐标。为了提高渲染性能,最好在模型或相机变化的时候调用tag
函数,尽量不在渲染函数中调用tag
函数
模型标签坐标计算的代码封装为一个函数,然后根据具体情况调用。
/**
* 网格模型添加标签
*/
function tag() {
/**
* 立方体世界坐标转屏幕坐标
*/
//创建一个三维向量作为世界坐标
const worldVector = new THREE.Vector3();
//获取网格模型boxMesh的世界坐标,赋值给worldVector
boxMesh.getWorldPosition(worldVector);
//世界坐标转标准设备坐标,standardVector是WebGL设备坐标
const standardVector = worldVector.project(camera);
// 根据WebGL标准设备坐标standardVector计算div标签在浏览器页面的坐标
const a = window.innerWidth / 2;
const b = window.innerHeight / 2;
const x = Math.round(standardVector.x * a + a); //标准设备坐标转屏幕坐标
const y = Math.round(-standardVector.y * b + b); //标准设备坐标转屏幕坐标
/**
* 设置标签元素的位置
*/
div.style.left = x + 'px';
//这里的130px主要是为了标签和模型有一定偏移,当然也可以不设置,两者叠加在一起
div.style.top = y - 130 + 'px';
}
在threejs周期性执行的渲染函数render中周期性执行函数tag()
// 渲染函数
function render() {
renderer.render(scene, camera); //执行渲染操作
// mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度
requestAnimationFrame(render); //请求再次执行渲染函数render,渲染下一帧
// 调用tag函数更新div标签的位置坐标
tag();
}
render();
threejs相机发生变化了才执行tag函数更新HTML元素坐标。
// 初始化的时候,先调用一次tag函数计算HTML元素坐标
tag();//注意渲染一次后执行,如果渲染前网格模型的位置不会更新
const controls = new THREE.OrbitControls(camera,renderer.domElement);
// 发生鼠标事件调用tag函数,比如通过该控件旋转threejs场景
controls.addEventListener('change', tag);
模型位置改变
当网格模型的在threejs中世界坐标位置发生变化的时候,网格模型在canvas画布上渲染的位置也会发生变化,所以网格模型对应的HTML坐标肯定要随着变化,也就是说要重新计算模型标签位置。
模型位置改变更新HTML标签坐标调用tag函数
// 渲染函数
function render() {
renderer.render(scene, camera); //执行渲染操作
// 网格模型运动boxMesh
if(boxMesh.position.z<100){
boxMesh.position.z+=1
}else{
boxMesh.position.z=0
}
requestAnimationFrame(render); //请求再次执行渲染函数render,渲染下一帧
// 调用tag函数更新HTML标签的位置坐标
tag();
}
render();
只在模型位置改变的时候重新计算坐标
// 渲染函数
function render() {
renderer.render(scene, camera); //执行渲染操作
// 网格模型运动boxMesh
if(boxMesh.position.z<150){
boxMesh.position.z+=3
// 只在模型位置改变的时候,调用执行tag函数重新计算HTML标签坐标
tag();
}
requestAnimationFrame(render); //请求再次执行渲染函数render,渲染下一帧
}
render();