五、3d场景的卡片展示的创建

        在我们3d的开发中,对某一些建筑和物体进行解释说明是非常常见的现象,那么就不得不说卡片的展示了,卡片展示很友好的说明了当前物体的状态,一目了然,下面就是效果图。

五、3d场景的卡片展示的创建_第1张图片

它主要有两个方法来实现,大量的图片建议使用canvas来实现,少量的可以使用标签实现。

1.canvas

思路:

        1将需要展示的内容画到canvas上。

        2将canvas生成为图片材质,创建一个Mesh对象放入场景中。

实现代码

 gltf.scene.traverse((child) => {
        if (child.type == 'Mesh') {
          child.toggle = (child) => {
            this.toppip(
              120,
              60,
              child.position.x,
              child.rotation.y + 160,
              child.position.z,
              child.name,
            );
          };
        }
      });
// 提示框的创建
  toppip (w, h, px, py, pz, text) {
    //用canvas生成图片
    let canvas = document.createElement('canvas');
    let ctx = canvas.getContext('2d');
    var devicePixelRatio = window.devicePixelRatio || 1;
    var backingStoreRatio = ctx.webkitBackingStorePixelRatio || 1;
    var dpr = devicePixelRatio / backingStoreRatio;
    canvas.width = Math.round(w * dpr);
    canvas.height = Math.round(h * dpr);
    canvas.style.width = w + 'px';
    canvas.style.height = h + 'px';
    ctx.scale(dpr, dpr);
    //制作矩形
    ctx.fillStyle = 'gray';
    ctx.fillRect(0, 0, w, h);
    //设置文字
    ctx.fillStyle = 'blue';
    ctx.font = '6px "楷体"';
    // ctx.fillText('这个平面将被贴在正方体前表面', 0, 20)
    let textWord = text;
    //文字换行
    let len = parseInt(textWord.length / 10);
    for (let i = 0; i < len + 1; i++) {
      let space = 10;
      if (i === len) {
        space = textWord.length - len * 10;
      }
      let word = textWord.substr(i * 10, space);
      ctx.fillText(word, 2, 4 * (i + 1));
    }
 //生成图片
    let url = canvas.toDataURL('image/png');
    let texture = new THREE.TextureLoader().load(url);
    //将图片构建到纹理中
    let geometry1 = new THREE.PlaneGeometry(w, h);
    let material1 = new THREE.MeshBasicMaterial({
      map: texture,
      side: THREE.DoubleSide,
      opacity: 1,
      transparent: true,
    });
    let rect = new THREE.Mesh(geometry1, material1);
    rect.rotation.y = Math.PI;
    rect.position.set(px, py, pz);
    this.scene.add(rect);
    return rect;
  }

2.div标签法

思路:1.在主页面创建一个空的DIV

  1. 将需要加入的标签加入,并创建CSS3DObject对象,
  2. 将css3dObject加入Scene

点击增加标签,判断是否已经存在,存在就不增加了

eventHub.on('spriteClick', (ele) => {
      var isCreateTag = false
      floor2Tags.forEach(p => {
        if (p.name == (ele.event.name + ele.i)) {
          isCreateTag = true
        }
      })
      if (!isCreateTag) {
        const css3dObject = createTag(ele.event, ele.i);
        css3dObject.visible = true;
        floor2Tags.push(css3dObject)
        scene.add(css3dObject)
      }
    })

创建标签

//添加标签和视频
function createTag (object3d, index) {
  // 创建各个区域的元素
  const element = document.createElement("div");
  var perNum = index * 10 + 10
  var percent = Math.ceil((perNum / 100) * 100);
  var deg1 = ((45 + 135) * percent) / 50 - 135;
  var deg2 = ((45 + 135) * (percent - 50)) / 50 - 135;
  element.className = "elementTag";
  element.innerHTML = `
    
     

实时监控${object3d.name + index}

     
     
       
           
       
       
           
       
       
         

${percent}

         

mg/m³

       
     
       
         

0.094TSP

         

0.044PM2.5

         

0.085PM10

       
     
   
  `;   const objectCSS3D = new CSS3DObject(element);   //加载视频   objectCSS3D.name = object3d.name + index   objectCSS3D.position.set(     object3d.position.x / 5 + 20,     100,     object3d.position.y / 5 - 10,   );   objectCSS3D.scale.set(0.2, 0.2, 0.2);   return objectCSS3D;}

以上就是两种创建标签的方法,如果还有更好的方法可能我还没有发现,如果有兴趣交流可以私信或者留言,看到会第一时间回复,下期我们说说如何让这个卡片一直面向观察摄像头。

你可能感兴趣的:(3D开发专栏,3d)