Three.js 快速入门教程 07 - 场景物体添加标注

在开发 3D 可视化的项目中,往往会碰到要加场景中添加标注的需求。Three.js 内置了CSS2DRendererCSS3DRenderer两种渲染器,可以和方便的将可以将 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();
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值