在开发 3D 可视化的项目中,往往会碰到要加场景中添加标注的需求。Three.js 内置了CSS2DRenderer和CSS3DRenderer两种渲染器,可以和方便的将可以将 HTML 元素与三维场景的内容相结合。
CSS2DRenderer
引入渲染器
import { CSS2DRenderer } from "three/addons/renderers/CSS2DRenderer.js";
import { CSS2DObject } from "three/addons/renderers/CSS2DRenderer.js";
如果是通过 npm 安装,可能需要通过下面方式引入
import { CSS2DRenderer } from "three/examples/jsm/renderers/CSS2DRenderer";
import { CSS2DObject } from "three/examples/jsm/renderers/CSS2DRenderer";
初始化渲染器
如同再一开始介绍的WebGLRenderer渲染器,CSS2DRenderer的初始化过程也十分相似
css2DRenderer = new CSS2DRenderer();
// 设置宽高
css2DRenderer.setSize(width, height);
// 将渲染器输出结果挂载到dom树上
document.body.appendChild(css2DRenderer.domElement);
由于 html 默认布局方式的因素,可以看到CSS2DRenderer追加的输出画面跑到原有 3D 场景的下面去了。这时我们需要重新调整定位布局方式,让两个渲染器的输出画面叠加在一起。
css2DRenderer.domElement.style.position = "absolute";
css2DRenderer.domElement.style.top = "0px";
这样一个基于CSS2DRenderer的渲染器就初始化完毕了,但为了方式叠加在上层的标注层影响了下层对鼠标事件的捕获,例如当我们添加了辅助工具相机轨道控制器OrbitControls,下层便无法通过鼠标去控制场景的平移、旋转和缩放了。
想解决这个问题也很简单
css2DRenderer.domElement.style.pointerEvents = "none";
通过这个设置便可让鼠标事件穿透到下层
增加标注
在添加标注前我们需要先准备标注内容的 html 片段
const divElement = document.createElement("div");
divElement.innerHTML = `
<div style="border: 1px #000000 solid;padding: 4px;">
<div>这是一段标注</div>
</div>
`;
然后创建CSS2DObject对象,并添加进场景中
const tag = new CSS2DObject(divElement);
// 设置标注位置
tag.position.set(50, 50, 50);
scene.add(tag);
css2DRenderer.render(scene, camera);
如果想更方便的添加到对应模型的位置上,可以使用之前介绍过的copy()方法
const tag = new CSS2DObject(divElement);
// 将位置调整为和模型相同
tag.position.copy(mesh.position);
scene.add(tag);
css2DRenderer.render(scene, camera);
这样便能在场景中看到标注内容了
循环渲染
和WebGLRenderer渲染器一样,CSS2DRenderer渲染器也要在一个循环中重复渲染,标注内容才能实时动态更新到画面上
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
// 添加到循环中
css2DRenderer.render(scene, camera);
}
完整代码如下
css2DRenderer = new CSS2DRenderer();
// 设置宽高
css2DRenderer.setSize(width, height);
// 将渲染器输出结果挂载到dom树上
document.body.appendChild(css2DRenderer.domElement);
css2DRenderer.domElement.style.position = "absolute";
css2DRenderer.domElement.style.top = "0px";
css2DRenderer.domElement.style.pointerEvents = "none";
const divElement = document.createElement("div");
divElement.innerHTML = `
<div style="border: 1px #000000 solid;padding: 4px;">
<div>这是一段标注</div>
</div>
`;
const tag = new CSS2DObject(divElement);
// 设置标注位置
tag.position.set(50, 50, 50);
scene.add(tag);
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
// 添加到循环中
css2DRenderer.render(scene, camera);
}
render();
CSS3DRenderer
CSS3DRenderer同样也是针对 HTML 标签的渲染器,因此它的用法和CSS2DRenderer十分相似。
不同之处在于CSS3DRenderer可以将 HTML 元素进行 3D 渲染,例如实现复杂的 3D 旋转、缩放、倾斜等高级效果。而CSS2DRenderer只支持位移变换效果,相当于是一个CSS3DRenderer的简化版本。
在实际项目中择使用哪个渲染器取决于需求和场景中对象的复杂程度。
引入渲染器
import { CSS3DRenderer } from "three/addons/renderers/CSS3DRenderer.js";
import { CSS3DObject } from "three/addons/renderers/CSS3DRenderer.js";
如果是通过 npm 安装,可能需要通过下面方式引入
import { CSS3DRenderer } from "three/examples/jsm/renderers/CSS3DRenderer";
import { CSS3DObject } from "three/examples/jsm/renderers/CSS3DRenderer";
使用渲染器
由于两者的用法十分相似,这里直接给出完整代码
css3DRenderer = new CSS3DRenderer();
// 设置宽高
css3DRenderer.setSize(width, height);
// 将渲染器输出结果挂载到dom树上
document.body.appendChild(css3DRenderer.domElement);
css3DRenderer.domElement.style.position = "absolute";
css3DRenderer.domElement.style.top = "0px";
css3DRenderer.domElement.style.pointerEvents = "none";
const divElement = document.createElement("div");
divElement.innerHTML = `
<div style="border: 1px #000000 solid;padding: 4px;">
<div>这是一段标注</div>
</div>
`;
const tag = new CSS3DObject(divElement);
// 设置标注位置
tag.position.set(50, 50, 50);
scene.add(tag);
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
// 添加到循环中
css3DRenderer.render(scene, camera);
}
render();
1161

被折叠的 条评论
为什么被折叠?



