Appearance
场景标注标签信息
CSS2DRenderer(HTML 标签)
1. 引入扩展库
js
// 引入CSS2渲染器CSS2DRenderer和CSS2模型对象CSS2DObject
import { CSS2DRenderer, CSS2DObject } from "three/addons/renderers/CSS2DRenderer.js";
2. 创建 HTML 标签元素
html
<div id="tag">标签内容</div>
3. CSS2 模型对象CSS2DObject
把一个 HTML 元素转化为一个类似 threejs 网格模型的对象添加到场景中
js
const div = document.getElementById("tag");
// HTML元素转化为threejs的CSS2模型对象
const tag = new CSS2DObject(div);
tag.position.set(50, 0, 50);
scene.add(tag);
// const group = new THREE.Group();
// group.add(tag);
4. CSS2 渲染器CSS2DRenderer
创建一个 CSS2 渲染器 CSS2DRenderer
jsconst css2Renderer = new CSS2DRenderer();
渲染 HTML 标签对应的 CSS2 模型对象
CSS2DObject
js// 渲染循环 function render() { css2Renderer.render(scene, camera); renderer.render(scene, camera); requestAnimationFrame(render); }
设置渲染输出标签的尺寸范围,一般和画布宽高一致
js// width, height:canvas画布宽高度 css2Renderer.setSize(width, height);
插入渲染结果
CSS2Renderer.domElement
jsdocument.body.appendChild(css2Renderer.domElement);
重新定位 需要将
CSS2Renderer
渲染结果和父元素画布重叠jscss2Renderer.domElement.style.position = "absolute"; css2Renderer.domElement.style.top = "0px";
HTML 标签遮挡 Canvas 画布事件
问题:由于css2Renderer
的渲染结果是重叠覆盖在原有 canvas 画布上,会导致相机控件的旋转、缩放等操作失效
解决方法:修改.style.pointerEvents
js
css2Renderer.domElement.style.pointerEvents = "none";
Canvas 尺寸变化(HTML 标签)
全屏布局
js
// 画布跟随窗口变化
window.onresize = function () {
const width = window.innerWidth;
const height = window.innerHeight;
// cnavas画布宽高度重新设置
renderer.setSize(width, height);
// HTML标签css2Renderer.domElement尺寸重新设置
css2Renderer.setSize(width, height);
camera.aspect = width / height;
camera.updateProjectionMatrix();
};
局部布局(要和画布重叠)
html
<div id="webgl" style="position: absolute;top: 60px;left: 200px"></div>
js
document.getElementById("webgl").appendChild(renderer.domElement);
document.getElementById("webgl").appendChild(css2Renderer.domElement);
- 尺寸跟随窗口变化
js
window.onresize = function () {
const width = window.innerWidth - 200; //canvas画布高度
const height = window.innerHeight - 60; //canvas画布宽度
renderer.setSize(width, height);
// HTML标签css2Renderer.domElement尺寸重新设置
css2Renderer.setSize(width, height);
camera.aspect = width / height;
camera.updateProjectionMatrix();
document.getElementById("left").style.height = height + "px";
};
标签位置不同设置方式
世界坐标获取模型位置
当网格模型有多重父对象,通过世界坐标得到标签位置坐标
js
mesh.position.set(50, 0, 50);
// mesh设置一个父对象meshGroup
const meshGroup = new THREE.Group();
meshGroup.add(mesh);
meshGroup.position.x = -100;
设置标签位置:
js
const tag = new CSS2DObject(div);
const worldPosition = new THREE.Vector3();
// 获取mesh的世界坐标(meshGroup.position和mesh.position累加结果)
mesh.getWorldPosition(worldPosition);
// mesh世界坐标复制给tag
tag.position.copy(worldPosition);
局部模型坐标系原点
如果把标签模型对象CSS2DObject
作为模型对象的子元素,标签默认是标注在模型的局部坐标系坐标原点
js
const div = document.getElementById("tag");
// HTML元素转化为threejs的CSS2模型对象
const tag = new CSS2DObject(div);
//标签tag作为mesh子对象,默认受到父对象位置影响
mesh.add(tag);
通过调整标签或模型坐标,改变标签在模型上的位置
js
//y轴正方向,平移高度一半
geometry.translate(0, 40, 0);
//圆锥mesh局部坐标系原点在自己底部时候,标签需要向上偏移圆锥自身高度
tag.position.y += 80;
CSS3DRenderer 渲染 HTML 标签
- 和 CSS2 渲染器
CSS2DRenderer
整体使用流程基本相同 - CSS3 渲染的标签会跟着场景相机同步缩放,而 CSS2 渲染的标签默认保持自身像素值
引入
jsimport { CSS3DRenderer } from "three/addons/renderers/CSS3DRenderer.js";
创建一个 CSS3 渲染器
CSS3DRenderer
jsconst css3Renderer = new CSS3DRenderer(); css3Renderer.setSize(width, height); // HTML标签<div id="tag"></div>外面父元素叠加到canvas画布上且重合 css3Renderer.domElement.style.position = "absolute"; css3Renderer.domElement.style.top = "0px"; //设置.pointerEvents=none,解决HTML元素标签对threejs canvas画布鼠标事件的遮挡 css3Renderer.domElement.style.pointerEvents = "none"; document.body.appendChild(css3Renderer.domElement);
执行渲染
jsfunction render() { css3Renderer.render(scene, camera); // ... requestAnimationFrame(render); }
适应尺寸变化
jswindow.onresize = function () { ... // HTML标签css3Renderer.domElement尺寸重新设置 css3Renderer.setSize(width,height); };
禁止CSS3DObject
标签对应 HTML 元素背面显示
html
<div id="tag" style="backface-visibility: hidden;">标签内容</div>
CSS3DRenderer
渲染的 HTML 标签尺寸
CSS3DRenderer
渲染的 HTML 元素,其像素尺寸与 three.js 中的场景模型尺寸相当
- 缩放标签
js
const div = document.getElementById("tag");
const tag = new CSS3DObject(div);
tag.scale.set(0.5, 0.5, 1); //缩放标签尺寸
- 标签偏移
js
tag.position.y += 10;
CSS3 精灵模型CSS3DSprite
相比于CSS3DObject
渲染,精灵模型渲染的标签可以跟着场景缩放、旋转,但自身的角度始终平行于 canvas 画布,不受旋转影响
js
const div = document.getElementById("tag");
// HTML元素转化为threejs的CSS3精灵模型`CSS3DSprite`
const tag = new CSS3DSprite(div);
//标签tag作为mesh子对象,默认标注在模型局部坐标系坐标原点
mesh.add(tag);
// 相对父对象局部坐标原点偏移80,刚好标注在圆锥
tag.position.y += 80;
标签局部遮挡鼠标事件
- 执行
new CSS3DObject(div)
的时候,会把 HTML 标签设置为.style.pointerEvents = 'auto'
。 - 因此,要在实例化
new CSS3DObject(div)
之后,手动修改 HTML 标签的.style.pointerEvents
属性,防止遮挡 canvas 画布的鼠标事件
js
const div = document.getElementById("tag");
// HTML元素转化为threejs的CSS3模型对象
const tag = new CSS3DObject(div);
// new CSS3DObject(div);之后设置style.pointerEvents
div.style.pointerEvents = "none";