项目源码:地址
使用CSS2DObject创建文字
1 引入CSS2DObject, CSS2DRenderer
import { CSS2DObject, CSS2DRenderer} from "three/examples/jsm/renderers/CSS2DRenderer"
2 render初始化
initCSSRender() {
this.CSSRender = new CSS2DRenderer();
this.CSSRender.setSize(window.innerWidth, 1080);
this.CSSRender.domElement.style.position = 'absolute';
this.CSSRender.domElement.style.top = 0;
this.container = document.getElementById("container");
this.container.appendChild(this.CSSRender.domElement);
}
3 创建css2dobject
create2DObject() {
var div = document.createElement('div');
/*给标签设置你想要的的样式*/
div.style.width = '200px';
div.style.height = '100px';
div.style.background = 'rgba(10,18,51,0.8)';
div.style.color = '#fff'
div.textContent = 'hahaha'
div.className = 'label'
const label = new CSS2DObject(div);
return label;
}
4 循环渲染
this.CSSRender.render(this.scene, this.camera);
遇到的问题:
(1) 页面中有两个renderer,一个WebGLRenderer, 一个CSS2DRenderer。
由于CSS2DRenderer在顶层,所以控制器的控制对象得改成CSS2DRenderer
this.controls = new OrbitControls(this.camera, this.CSSRender.domElement);
(2) 随着放大的过程,会发现场景中模型变大了,但是文字标签却‘相对变小’了。
照理说文字标签应该和模型同步变化才对吧。。试图给div增加tansform:scale属性,发现怎么也加不上去。
查看源码,发现在渲染object时,会给他加上transform属性,所以之前给div加这个属性被覆盖掉了而加不上去。
修改源码:
首先在循环渲染函数中监听球坐标系的半径的变化(视野的放大与缩小)
animate() {
var radius = this.controls.getSpherical().radius; //通过修改orbitcontrol源码拿到的,见前面文章
if(this.roof) { //项目中加载的模型房顶
if(radius && radius < 22) { //放大到某种程度,隐藏屋顶,显示文字
this.roof.children[0].material.visible = false;
for(let label of document.getElementsByClassName('label')) {
label.style.visibility = 'visible';
label.$data = radius; //这里给每个标签绑定radius
}
} else { 缩小到某种程度,显示屋顶,隐藏文字
this.roof.children[0].material.visible = true;
for(let label of document.getElementsByClassName('label')) {
label.style.visibility = 'hidden'
}
}
}
this.renderer.render(this.scene, this.camera);
this.CSSRender.render(this.scene, this.camera);
this.requestId = requestAnimationFrame(this.animate);
}
修改CSS2DRenderer源码:
根据循环渲染函数中不断改变的视野大小来控制元素的缩放
(3)层次问题
由于要显示文字,所以CSS2DRenderer 在顶层,当改变视角时可能会出现标签跑到围墙外的情况,其实就是因为他在最上层,盖不住。暂时没找到好的解决方法,
只好通过限制缩放大小范围,旋转角度来控制。有好办法希望多多指教呀~
// 视角最小距离
this.controls.minDistance = 12;
// 视角最远距离
this.controls.maxDistance = 100;
// 最大角度
this.controls.maxPolarAngle = Math.PI/4;
(4)今天又遇到一个问题,旋转时发现文字会变糊,上网查了一下原因,说是transform:translate(x, y)中x,y不是整数,导致移动的位置不是很精确所以出现了模糊。于是用Math.round()函数取了一下整,发现的确变清晰了。
对,还是修改源码部分