CSS3DRenderer标注模型

773 阅读4分钟

效果图

mmm.jpg

HTML

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Three.js中文网:http://www.webgl3d.cn/</title>
  <style>
    body {
      margin: 0;
      overflow: hidden;
    }
    .tag {
      box-shadow: 0 0 2px #00ffff inset;
      background: linear-gradient(#00ffff, #00ffff) left top,
        linear-gradient(#00ffff, #00ffff) left top,
        linear-gradient(#00ffff, #00ffff) right bottom,
        linear-gradient(#00ffff, #00ffff) right bottom;
      background-repeat: no-repeat;
      background-size: 1px 6px, 6px 1px;
      background-color: rgba(0, 0, 0, 0.4);
      color: #ffffff;
      font-size:16px;
      padding:4px 10px;     
    }
  </style>
</head>

<body>
  <script type="module">
    import {renderer} from './RenderLoop.js'
    //Three.js渲染结果Canvas画布插入到body元素中
    document.body.appendChild(renderer.domElement);
  </script>
</body>

</html>

tag.js(div元素包装为CSS3模型对象CSS3DObject)

import { CSS3DRenderer, CSS3DObject } from '../../../../three.js-r123/examples/jsm/renderers/CSS3DRenderer.js';
// 创建一个HTML标签
function tag(name) {
  // 创建div元素(作为标签)
  var div = document.createElement('div');
  div.innerHTML = name;
  div.classList.add('tag');
  //div元素包装为CSS3模型对象CSS3DObject
  var label = new CSS3DObject(div);
  div.style.pointerEvents = 'none';//避免HTML标签遮挡三维场景的鼠标事件
  // 设置HTML元素标签在three.js世界坐标中位置
  // label.position.set(x, y, z);
  //缩放CSS3DObject模型对象
  label.scale.set(0.2,0.2,0.2);//根据相机渲染范围控制HTML 3D标签尺寸
  label.rotateY(Math.PI/2);//控制HTML标签CSS3对象姿态角度
  // label.rotateX(-Math.PI/2);
  return label;//返回CSS3模型标签      
}

// 创建一个CSS3渲染器CSS3DRenderer
var labelRenderer = new CSS3DRenderer();
labelRenderer.setSize(window.innerWidth, window.innerHeight);
labelRenderer.domElement.style.position = 'absolute';
// 相对标签原位置位置偏移大小
labelRenderer.domElement.style.top = '0px';
labelRenderer.domElement.style.left = '0px';
// //设置.pointerEvents=none,以免模型标签HTML元素遮挡鼠标选择场景模型
labelRenderer.domElement.style.pointerEvents = 'none';
document.body.appendChild(labelRenderer.domElement);

export { tag, labelRenderer }

model.js(模型加载)

// 引入Three.js
import * as THREE from '../../../../three.js-r123/build/three.module.js';
// 引入gltf模型加载库GLTFLoader.js
import { GLTFLoader } from '../../../../three.js-r123/examples/jsm/loaders/GLTFLoader.js';

import { tag } from './tag.js';//HTML标签相关代码

var model = new THREE.Group();//声明一个组对象,用来添加加载成功的三维场景
var loader = new GLTFLoader(); //创建一个GLTF加载器
loader.load("./scene/model.glb", function (gltf) {//gltf加载成功后返回一个对象
    // console.log('控制台查看gltf对象结构', gltf);
    // console.log('gltf对象场景属性', gltf.scene);
    // 递归遍历gltf.scene
    gltf.scene.traverse(function (object) {
        if (object.type === 'Mesh') {
            // 批量更改所有Mesh的材质
            object.material = new THREE.MeshLambertMaterial({
                map: object.material.map, //获取原来材质的颜色贴图属性值
                color: object.material.color, //读取原来材质的颜色
            })
        }
    })
    var group = gltf.scene.getObjectByName('粮仓');
    //console.log('粮仓', group);
    group.traverse(function (obj) {
        if (obj.type === 'Mesh') {
            var label = tag(obj.name);//把粮仓名称obj.name作为标签
            var pos = new THREE.Vector3();
            obj.getWorldPosition(pos);//获取obj世界坐标、
            // 粮仓世界坐标对应粮仓底部圆心位置,如果标签像标注在粮仓底部,需要加上粮仓整体高度
            if(obj.parent.name=="立筒仓"){
                pos.y+=36;//加上粮仓顶部高度
            }else if(obj.parent.name=="浅圆仓"){
                pos.y+=20;
            }else if(obj.parent.name=="平房仓"){
                pos.y+=17;
            }
            label.position.copy(pos);//标签标注在obj世界坐标
            model.add(label);//标签插入model组对象中         
        }
    })
    // var PGroup = gltf.scene.getObjectByName('平房仓');
    // PGroup.children.forEach(function (Mesh) {
    //     var label = tag(Mesh.name);
    //     var pos = new THREE.Vector3();
    //     Mesh.getWorldPosition(pos);//获取mesh世界坐标
    //     label.position.copy(pos);//标签标注在mesh世界坐标
    //     model.add(label);//标签插入model组对象中                       
    // })
    //把gltf.scene中的所有模型添加到model组对象中
    model.add(gltf.scene);
})
export { model }

以下文件为环境相关的常规配置文件

RendererCamera.js(相机)

// 引入Three.js
import * as THREE from '../../../three.js-r123/build/three.module.js';
// 引入Three.js扩展库
import { OrbitControls } from '../../../three.js-r123/examples/jsm/controls/OrbitControls.js';

// width和height用来设置Three.js输出Canvas画布尺寸,同时用来辅助设置相机渲染范围
var width = window.innerWidth; //窗口文档显示区的宽度
var height = window.innerHeight; //窗口文档显示区的高度
/**
* 相机设置
*/
//  透视投影
var camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000);
camera.position.set(318, 162, 204);//通过相机控件OrbitControls旋转相机,选择一个合适场景渲染角度
camera.lookAt(0, 0, 0);
/**
 * 创建渲染器对象
 */
var renderer = new THREE.WebGLRenderer({
    antialias: true, //开启锯齿
});
renderer.setPixelRatio(window.devicePixelRatio);//设置设备像素比率,防止Canvas画布输出模糊。
renderer.setSize(width, height); //设置渲染区域尺寸

// renderer.domElement表示Three.js渲染结果,也就是一个HTML元素(Canvas画布)
// document.body.appendChild(renderer.domElement); //body元素中插入canvas对象

// 设置three.js背景颜色 和雾化颜色相配   
renderer.setClearColor(0x005577, 1);
renderer.outputEncoding = THREE.sRGBEncoding;//解决加载gltf格式模型纹理贴图和原图不一样问题

//创建控件对象  控件可以监听鼠标的变化,改变相机对象的属性
// 旋转:拖动鼠标左键
// 缩放:滚动鼠标中键
// 平移:拖动鼠标右键
var controls = new OrbitControls(camera, renderer.domElement);

export { renderer, camera };

index.js(光源)

// 场景总文件
// 引入Three.js
import * as THREE from '../../../../three.js-r123/build/three.module.js';
import { model } from './model.js';
/**
 * 创建场景对象Scene
 */
var scene = new THREE.Scene();
scene.add(model);//粮仓基地三维模型添加到场景中

// 设置雾化效果,雾的颜色和背景颜色相近,这样远处网格线和背景颜色融为一体
scene.fog = new THREE.Fog(0x005577, -100, 1000);
/**
* 光源设置
*/
// 平行光1
var directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
directionalLight.position.set(400, 200, 300);
scene.add(directionalLight);
// 平行光2
var directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.5);
directionalLight2.position.set(-400, -200, -300);
scene.add(directionalLight2);
//环境光
var ambient = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambient);

// Three.js三维坐标轴 三个坐标轴颜色RGB分别对应xyz轴
var axesHelper = new THREE.AxesHelper(250);
// scene.add(axesHelper);

export { scene };

RenderLoop.js(执行渲染)

import { scene } from './scene/index.js'//Three.js三维场景
import { renderer, camera } from './RendererCamera.js'//渲染器对象和相机对象
import { labelRenderer } from './scene/tag.js';//HTML标签相关代码
// 渲染循环
function render() {
  labelRenderer.render(scene, camera); //渲染HTML标签对象
  renderer.render(scene, camera); //执行渲染操作
  requestAnimationFrame(render); //请求再次执行渲染函数render,渲染下一帧
  // console.log(camera.position);//通过相机控件OrbitControls旋转相机,选择一个合适场景渲染角度
}
render();
export {renderer}