threejs 创建CSS3DSprite精灵标签, 可以更新位置及内容(封装)
ThreeCss3dSprite.js
工具类
js
import { CSS3DRenderer, CSS3DSprite } from "../js/three.js/examples/jsm/renderers/CSS3DRenderer.js";
class ThreeCss3dSprite {
constructor() {
this.sprite = null;
this.labelRenderer = null;
this.isShow = true;
this.elementDiv = null;
}
/**
* 更新标签内容及位置
* @param {Number} x x位置
* @param {Number} y y位置
* @param {Number} z z位置
* @param {*} parentGroup 父模型
* @param {Array<String>} contentList 内容列表 ['经度:111', '纬度:222', '高度:333']
*/
updateSprite(x, y, z, parentGroup, contentList = []) {
if (this.sprite) {
this.elementDiv.innerHTML = this.#getSpriteText(contentList);
this.sprite.position.set(x, y, z);
} else {
this.#initSprite(x, y, z, parentGroup, contentList);
}
}
/**
* 设置标签显示或隐藏
* @param {Boolean} visible 是否显示
*/
setVisible(visible) {
this.isShow = visible;
this.sprite.visible = visible;
}
/**
* 刷新渲染(在Threejs屏幕刷新方法中调用)
* @param {*} scene 场景
* @param {*} camera 相机
*/
render(scene, camera) {
if (this.labelRenderer) {
this.labelRenderer.render(scene, camera);
}
}
/**
* 创建标签
* @param {Number} x x位置
* @param {Number} y y位置
* @param {Number} z z位置
* @param {*} parentGroup 父模型
* @param {Array<String>} contentList 内容列表 ['经度:111', '纬度:222', '高度:333']
*/
#initSprite(x, y, z, parentGroup, contentList = []) {
// 创建渲染器
this.labelRenderer = new CSS3DRenderer();
this.labelRenderer.setSize(window.innerWidth, window.innerHeight);
this.labelRenderer.domElement.style.position = "absolute";
this.labelRenderer.domElement.style.top = "0px";
document.body.appendChild(this.labelRenderer.domElement);
// 创建容器
this.elementDiv = document.createElement("div");
this.elementDiv.className = "tooltip";
this.elementDiv.style.width = "12px";
this.elementDiv.style.backgroundColor = "rgba(255, 255, 255, 0.5)";
this.elementDiv.style.borderRadius = "0.5px";
this.elementDiv.style.padding = "1px";
this.elementDiv.style.color = "#000";
this.elementDiv.innerHTML = this.#getSpriteText(contentList);
// 创建精灵标签
this.sprite = new CSS3DSprite(this.elementDiv);
this.sprite.visible = this.isShow;
this.sprite.position.set(x, y, z);
parentGroup.add(this.sprite);
}
/**
* 返回标签内容
* @param {Array<String>} contentList 内容列表 ['经度:111', '纬度:222', '高度:333']
* @returns 标签内容
*/
#getSpriteText(contentList = []) {
let tooltipContent = "";
contentList.forEach(item => {
tooltipContent += `<div style="font-size:1px;">${item}</div>`;
});
return tooltipContent;
}
}
export { ThreeCss3dSprite };
- 调用
js
// 导入
import { ThreeCss3dSprite } from "@/utils/ThreeCss3dSprite.js";
// 创建对象
var sprite = new ThreeCss3dSprite();
// 在刷新方法中调用render
function animate() {
requestAnimationFrame(animate);
sprite.render(scene, camera);
}
// 创建或更新标签
const newPosition = new THREE.Vector3(100, 100, 100);
let list = [`经度: 200`, `纬度: 300`, `深度: 500`];
sprite.updateSprite(newPosition.x, newPosition.y, newPosition.z, scene, list);