Threejs之场景标注标签信息CSS2DRenderer

参考资料

知识点

注:基于Three.jsv0.155.0

  • CSS2DRenderer(HTML标签)
  1. HTML标签遮挡Canvas画布事件
  2. Canvas尺寸变化(HTML标签)
  3. 标签位置不同设置方式
  4. 标签位置(标注工厂设备)
  5. 标签指示线或箭头指向标注点
  6. 鼠标选中模型弹出标签(工厂)
  7. 单击按钮关闭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>
  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Three.js 中,要显示 2D 文本标签可以使用 CSS2DRendererCSS2DRenderer 可以将 2D 元素渲染在 Three.js场景中,可以使用标准 HTML 和 CSS 样式来创建标签。这允许我们非常方便地创建自定义的标签,比如显示对象名称、文字、标注等等。 下面是一个简单的使用 CSS2DRenderer 显示文本标签的示例: ```javascript // 创建 CSS2DRenderer var renderer = new THREE.CSS2DRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // 创建场景和相机 var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); // 创建文本标签 var label = document.createElement('div'); label.className = 'label'; label.textContent = 'Hello, World!'; var labelObj = new THREE.CSS2DObject(label); labelObj.position.set(0, 0, 0); scene.add(labelObj); // 渲染循环 function render() { requestAnimationFrame(render); renderer.render(scene, camera); } render(); ``` 在上面的代码中,我们首先创建了一个 CSS2DRenderer,然后创建了场景和相机。接着,我们创建了一个 div 元素作为文本标签,设置了它的 className 和 textContent 属性,并将其包装为一个 CSS2DObject 对象,设置其位置并添加到场景中。最后,我们启动了渲染循环。 需要注意的是,CSS2DRenderer 渲染的元素是基于屏幕坐标系的,它们的位置是相对于窗口左上角的像素位置。如果需要将它们放置在 Three.js 中的某个物体上,需要通过计算其位置和旋转来实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值