threejs 太阳系给星球添加文字标注

threejs yekong

之前我们实现threejs 太阳系提高性能 共享Geometry Material,接下来我们给星球来添加文字标注。给星球添加文字标注就是通过css2d给模型添加标注

threejs 太阳系给星球添加文字标注

给星球添加文字标签,我们使用css2d来实现。

标签方法

首先我们创建一个标签方法,用来接收名称

function tag(name) {
    var that = this;
    // 创建div元素(作为标签)
    var div = document.createElement('div')
    div.innerHTML = `<div class="tags">${name}</div>`
    div.classList.add('tag')
    //div元素包装为CSS2模型对象CSS2DObject
    var label = new CSS2DObject(div)
    div.style.pointerEvents = 'none'//避免HTML标签遮挡三维场景的鼠标事件
    return label//返回CSS2模型标签
}

创建css2d渲染器

创建一个css2d渲染器,用来渲染我们创建的标签

// 标签创建
var labelRenderer = new CSS2DRenderer()
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'

将这个渲染器插入到div中

that.$refs.home.appendChild(labelRenderer.domElement)

创建模型时连同标签一起插入

我们在创建星球的时候,创建标签,将星球添加到场景后,在通过getObjectByName方法来获取场景中星球的3维坐标,使用getWorldPosition将3维坐标转为世界坐标。赋值给标签,然后插入到场景中。并将这些tag标签单独加入一个数组中,以便于后期我们更新标签坐标做准备。

this.list.forEach((type, index) => {
  var mesh = addGeoMetry(geometry, type.URL, type.R)
  mesh.name = type.name
  mesh.data = type
  mesh.angle = 2 * Math.PI * Math.random();
  scene.add(mesh); //网格模型添加到场景中
  // 添加标签
  var group = scene.getObjectByName(type.name)
  var label = tag(group.name)//把名称obj.name作为标签
  var pos = new THREE.Vector3()
  group.getWorldPosition(pos)//获取obj世界坐标、
  label.position.copy(pos)//标签标注在obj世界坐标
  label.name = group.name
  scene.add(label)//标签插入model组对象中
  that.labelLst.push(label)
  // 添加标签
  // 创建轨道
  if (type.revolutionR) {
    var line = circle(lineGeometry, material, type.revolutionR)
    scene.add(line)
  }
});

渲染

因为添加了css2d渲染器,所以我们需要将css2d也加入渲染函数中。

renderer.render(scene, camera); //执行渲染操作
labelRenderer.render(scene, camera); //执行渲染标签层

在这里我们除了要更新星球的坐标,也需要更新标签的位置,在遍历更新星球时,我们也通过这个星球的名称来获取对应名称的css2d标签并更新其坐标

that.labelLst.forEach((type2) => {
    if (type2.name == type.name) {
      type2.position.set(x, 0, z);
    }
});

render渲染方法完整

function render() {
  scene.children.forEach((type) => {
    if (type.type == 'Mesh') {
      type.rotateY(0.01)
      type.angle += 0.01;// 每次执行render角度新增加
      var x = type.data.revolutionR * Math.sin(type.angle);//地球x坐标计算
      var z = type.data.revolutionR * Math.cos(type.angle);//地球z坐标计算
      // 设置地球xz坐标,实现公转动画
      type.position.set(x, 0, z);
      that.labelLst.forEach((type2) => {
        if (type2.name == type.name) {
          type2.position.set(x, 0, z);
        }
      });
    }
  });
  renderer.render(scene, camera); //执行渲染操作
  labelRenderer.render(scene, camera); //执行渲染标签层
  requestAnimationFrame(render); //请求再次执行渲染函数render,渲染下一帧
}

效果演示

演示地址

threejs 太阳系给星球添加文字标注

视频课程介绍

当前笔记是Three.js太阳系案例 threejs视频教程 星球和太阳添加标签 学习实践笔记

相关文件下载地址
此资源需支付 ¥5 后下载
支付宝购买扫右侧红包码购买更优惠,如无法下载请联系微信:17331886870
喜欢
threejs 太阳系给星球添加文字标注