参考资料
知识点
注:基于Three.jsv0.155.0
- CSS2DRenderer(HTML标签)
- HTML标签遮挡Canvas画布事件
- Canvas尺寸变化(HTML标签)
- 标签位置不同设置方式
- 标签位置(标注工厂设备)
- 标签指示线或箭头指向标注点
- 鼠标选中模型弹出标签(工厂)
- 单击按钮关闭HTML标签
总体思路
- 1.HTML元素创建标签
- 2.CSS2模型对象
CSS2DObject
- 3.CSS2渲染器
CSS2DRenderer
- 4.
CSS2Renderer.domElement
重新定位
代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Three.js</title>
</head>
<body>
<div id="container"></div>
<div id="tag">标签内容</div>
</body>
<!-- 具体路径配置,你根据自己文件目录设置,我的是课件中源码形式 -->
<script type="importmap">
{
"imports": {
"three": "./js/three.module.js",
"three/addons/": "../three.js/examples/jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { CSS2DRenderer,CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
const width = 800
const height = 500
// 场景
const scene = new THREE.Scene();
const geometry = new THREE.BoxGeometry(25, 100, 50);
geometry.translate(0, 50, 0);
// 材质
const material = new THREE.MeshBasicMaterial({
color: 0x00ff00,
transparent: true,
});
// mesh顶部中心添加标注,顶部中心坐标是(0,100,0)
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// mesh设置一个父对象meshGroup
const meshGroup = new THREE.Group();
meshGroup.add(mesh);
// mesh位置受到父对象局部坐标.positionn影响
meshGroup.position.x = -100;
scene.add(meshGroup);
// 环境光
const ambientLight = new THREE.AmbientLight( 0xffffff, 0.2);
scene.add( ambientLight );
// 坐标系
const axes = new THREE.AxesHelper(200);
scene.add(axes);
const camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000);
camera.position.set(200, 200, 200);
camera.lookAt(scene.position);
// 渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
// renderer.setClearColor(0x000000, 0.5);
renderer.render(scene, camera);
// 渲染器背景透明
document.body.appendChild(renderer.domElement);
// 标签
const div = document.getElementById('tag');
// HTML元素转化为threejs的CSS2模型对象
const tag = new CSS2DObject(div);
// tag.position.set(-50,0,50);
// const worldPosition = new THREE.Vector3();
// mesh.getWorldPosition(worldPosition);
// tag.position.copy(worldPosition);
// scene.add(tag);
mesh.add(tag);
scene.add(mesh);
const pos = geometry.attributes.position;
// 获取几何体顶点1的xyz坐标,设置标签局部坐标.position属性
tag.position.set(pos.getX(0),pos.getY(0),pos.getZ(0));
const group = new THREE.Group();
// 最后meshGroup和tag放在同一个父对象中即可
group.add(meshGroup,tag);
scene.add(group);
// 创建一个CSS2渲染器CSS2DRenderer
const css2Renderer = new CSS2DRenderer();
css2Renderer.setSize(width, height);
css2Renderer.render(scene, camera);
document.body.appendChild(css2Renderer.domElement);
css2Renderer.domElement.style.position = 'absolute';
css2Renderer.domElement.style.top = '0';
// renderer.domElement.style.marginTop = '200px';
// css2Renderer.domElement.style.top = '200px';
css2Renderer.domElement.style.color = 'red';
css2Renderer.domElement.style.fontSize = '20px';
css2Renderer.domElement.style.pointerEvents = 'none';
renderer.domElement.style.zIndex = -1;
css2Renderer.domElement.style.zIndex = 1;
// 控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.addEventListener('change', () => {
// 因为动画渲染了,所以这里可以省略
renderer.render(scene, camera);
});
// 画布跟随窗口变化
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();
};
</script>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Three.js</title>
</head>
<body>
<div id="container"></div>
<div id="tag">标签内容</div>
</body>
<!-- 具体路径配置,你根据自己文件目录设置,我的是课件中源码形式 -->
<script type="importmap">
{
"imports": {
"three": "./js/three.module.js",
"three/addons/": "../three.js/examples/jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { CSS2DRenderer,CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
const width = 800
const height = 500
// 场景
const scene = new THREE.Scene();
const geometry = new THREE.ConeGeometry(25, 80);
// 材质
const material = new THREE.MeshBasicMaterial({
color: 0x00ff00,
transparent: true,
});
const mesh = new THREE.Mesh(geometry, material);
// 可视化模型的局部坐标系
scene.add(mesh);
// 环境光
const ambientLight = new THREE.AmbientLight( 0xffffff, 0.2);
scene.add( ambientLight );
// 坐标系
const axes = new THREE.AxesHelper(200);
scene.add(axes);
const camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000);
camera.position.set(200, 200, 200);
camera.lookAt(scene.position);
// 渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
// renderer.setClearColor(0x000000, 0.5);
renderer.render(scene, camera);
// 渲染器背景透明
document.body.appendChild(renderer.domElement);
// 标签
const div = document.getElementById('tag');
// HTML元素转化为threejs的CSS2模型对象
const tag = new CSS2DObject(div);
mesh.add(tag);
// scene.add(tag);
//y轴正方向,平移高度一半
geometry.translate(0, 40, 0);
//圆锥mesh局部坐标系原点在自己底部时候,标签需要向上偏移圆锥自身高度
tag.position.y += 40;
// 创建一个CSS2渲染器CSS2DRenderer
const css2Renderer = new CSS2DRenderer();
css2Renderer.setSize(width, height);
css2Renderer.render(scene, camera);
document.body.appendChild(css2Renderer.domElement);
css2Renderer.domElement.style.position = 'absolute';
css2Renderer.domElement.style.top = '0';
css2Renderer.domElement.style.color = 'red';
css2Renderer.domElement.style.fontSize = '20px';
// 控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.addEventListener('change', () => {
// 因为动画渲染了,所以这里可以省略
renderer.render(scene, camera);
});
// 画布跟随窗口变化
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();
};
</script>
</html>