three.js加载三维GLB文件,查看三维模型,并显示实时
·
要将压力值显示到 3D 模型上(而不是仅在 HTML 页面上显示),我们可以使用 Three.js 的 CSS2DRenderer 或 Sprite + Canvas 纹理 方式。
其中,CSS2DRenderer 是最简单、清晰、可交互且支持中文的方式,特别适合在模型特定位置叠加文本标签(如“压力: 45.2 kPa”)。
✅ 解决方案:使用 CSS2DRenderer 在模型上方显示压力值
✨ 优势:
- 文字始终面向屏幕(不会随模型旋转变形)
- 支持 HTML/CSS 样式(字体、颜色、背景等)
- 可绑定到模型的任意位置(如顶部、中心、某个零件)
📌 实现步骤:
- 引入
CSS2DRenderer和CSS2DObject - 创建一个
<div>作为压力标签 - 将该标签绑定到模型的某个位置(如模型中心或顶部)
- 每10秒更新该标签内容
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>3D模型 + 模型上显示压力值(修复版)</title>
<style>
body { margin: 0; overflow: hidden; font-family: Arial, sans-serif; }
canvas { display: block; }
#info {
position: absolute;
top: 10px;
left: 10px;
color: white;
background: rgba(0,0,0,0.7);
padding: 10px;
border-radius: 5px;
z-index: 100;
}
.pressure-label {
color: cyan;
font-size: 18px;
font-weight: bold;
background: rgba(0, 0, 0, 0.6);
padding: 8px 12px;
border-radius: 6px;
white-space: nowrap;
/* 不拦截鼠标事件 */
pointer-events: none;
}
</style>
</head>
<body>
<div id="info">正在加载模型... 请等待</div>
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/loaders/GLTFLoader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/loaders/TextureLoader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/renderers/CSS2DRenderer.js"></script>
<script>
// 场景
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x222222); // 深色背景更易看清标签
// 相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 5);
// WebGL 渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.gammaOutput = true;
renderer.gammaFactor = 2.2;
document.body.appendChild(renderer.domElement);
// CSS2D 渲染器(用于标签)
const labelRenderer = new THREE.CSS2DRenderer();
labelRenderer.setSize(window.innerWidth, window.innerHeight);
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.top = '0px';
labelRenderer.domElement.style.pointerEvents = 'none'; // 👈 关键:允许鼠标穿透
document.body.appendChild(labelRenderer.domElement);
// 光照
const ambientLight = new THREE.AmbientLight(0xffffff, 0.8);
scene.add(ambientLight);
const dirLight = new THREE.DirectionalLight(0xffffff, 1);
dirLight.position.set(5, 5, 5);
scene.add(dirLight);
// 控制器(绑定到 WebGL 的 canvas)
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
let pressureLabelDiv = null;
let pressureLabelObject = null;
// 模拟压力值
function getPressure() {
return (Math.random() * 100).toFixed(1);
}
function updatePressure() {
if (pressureLabelDiv) {
pressureLabelDiv.textContent = `压力: ${getPressure()} kPa`;
}
}
// 加载模型
const loader = new THREE.GLTFLoader();
loader.load(
'well.glb', // 确保该文件存在!否则标签不会创建
(gltf) => {
const model = gltf.scene;
scene.add(model);
// 居中 & 缩放
const box = new THREE.Box3().setFromObject(model);
const center = box.getCenter(new THREE.Vector3());
const size = box.getSize(new THREE.Vector3());
const maxDim = Math.max(size.x, size.y, size.z);
const fov = camera.fov * (Math.PI / 180);
const dist = Math.abs(maxDim / 2 / Math.tan(fov / 2)) * 1.5;
camera.position.set(center.x, center.y, center.z + dist);
controls.target.copy(center);
controls.update();
// 创建压力标签
pressureLabelDiv = document.createElement('div');
pressureLabelDiv.className = 'pressure-label';
pressureLabelDiv.textContent = '压力: -- kPa';
pressureLabelObject = new THREE.CSS2DObject(pressureLabelDiv);
// 放在模型顶部上方
pressureLabelObject.position.copy(center);
pressureLabelObject.position.y += size.y / 2 + 0.3; // 微调高度
scene.add(pressureLabelObject);
document.getElementById('info').textContent = '模型加载完成';
updatePressure(); // 立即显示初始值
},
(xhr) => {
if (xhr.lengthComputable) {
const percent = (xhr.loaded / xhr.total * 100).toFixed(0);
document.getElementById('info').textContent = `加载中 ${percent}%`;
}
},
(error) => {
console.error('模型加载失败:', error);
document.getElementById('info').textContent = '❌ 模型加载失败,请检查 well.glb 是否存在';
}
);
// 每10秒更新
setInterval(updatePressure, 10000);
// 窗口缩放
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
labelRenderer.setSize(window.innerWidth, window.innerHeight);
});
// 渲染循环
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
labelRenderer.render(scene, camera); // 必须调用
}
animate();
</script>
</body>
</html>

更多推荐
所有评论(0)