three.js 添加html内容、文本

需求:

1、在场景内添加html元素并动态更新

2、html内容需跟随场景变化

方案:

有几种方案

一、直接将文本P成为图片 然后在场景内加载 2D模型将该图片当作模型贴图处理

二、将html内容通过canvas 然后再以模型的方式加载进场景(不做详细解释)

1、创建

    getTextCanvas(text){ 
      // 创建贴图文字
        var width=512, height=256; 
        var canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = height;
        var ctx = canvas.getContext('2d');
        ctx.fillStyle = '#008080';
        ctx.fillRect(0, 0, width, height);
        ctx.font = 50+'px " bold';
        ctx.fillStyle = '#FFFFFF';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.fillText(text, width/2,height/2); 
        return canvas;
    },

2、加载

        var geometry = new THREE.PlaneGeometry(e.w, e.h, 30 );
        var material = new THREE.MeshBasicMaterial(
          {
            // map:new THREE.CanvasTexture(this.getTextCanvas(e.content)),  // canvas 画图方式
            map:new THREE.TextureLoader().load(`${this.GLOBAL.service}img/043img/btn/${e.content}.png`), 
            } );
        var introduce = new THREE.Mesh( geometry, material );
        introduce.name= "model introduce"
        // plane.location=i.location
        introduce.modeltype= 3 //
        introduce.position.set(x,y,z);
        introduce.lookAt(0,y,0)
        skyBox.add(introduce);

三、用CSS2DObject进行处理

1、增加渲染器 CSS2DRenderer  

2、使用 three.js 的 CSS2DObject 模块 进行html内容转换 并绑定模型 

官网案例  

官网示例代码 

一般需要这个功能的肯定都不是新手了,所以内容就不做介绍了,这里只需要关注几点

1、增加渲染器(原有的渲染器不动,新增一个CSS2DRenderer渲染器 ):

  addhtml() {
      // 场景渲染器

      this.renderer = new THREE.WebGLRenderer();
      this.renderer.shadowMapEnabled = true;
      this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
      // this.renderer.gammaOutput = true;
      this.renderer.gammaFactor = 2.2;
      // this.renderer.setClearColor(new THREE.Color(0xcce0ff));

      this.renderer.setSize(window.innerWidth*0.95, window.innerHeight*0.95);
      document
        .getElementById("container")
        .appendChild(this.renderer.domElement);
      // window.addEventListener("resize", () => this.onWindowResize());
      
      this.labelRenderer = new CSS2DRenderer();  // 新增的渲染器
      this.labelRenderer.setSize(window.innerWidth*0.95, window.innerHeight*0.95);
      // this.labelRenderer.domElement.style.position = 'absolute';
      // this.labelRenderer.domElement.style.top = 0;
      this.labelRenderer.domElement.style="pointer-events: auto;position: absolute;top: 0px;"  // 处理新的渲染器
      document.getElementById("container").appendChild(this.labelRenderer.domElement);
   },
    animate() {
      // 渲染
      this.renderer.render(this.scene, this.camera);
      this.labelRenderer.render(this.scene, this.camera);// 加载新渲染器
      window.requestAnimationFrame(() => this.animate());
      TWEEN.update();
    },

注意:官网示例只适应于全屏的情况 不全屏的情况请自行调整

2、增加内容容器:

<template>
  <div class="project">
    <div id="text" style="    position: relative; 30%;
    height: 100px;
    color: #fff;">
      {{modelnumber}}
    </div>
    <div id="container">
 
  </div>
</template>

3、绑定模型(创建模型什么的这里就不解释了):

    // 2D 文本
    // let laberDiv = document.createElement('div');//创建div容器
    let laberDiv = document.getElementById('text');//获取div容器
        // laberDiv.innerHTML=`
        // <div class="leftTip" style="">
        //    ${this.modelnumber}
        // </div>
        // `;
        laberDiv.style.marginTop = '-1em';
    let pointLabel = new CSS2DObject(laberDiv);   
    pointLabel.position.set(0,100,0);  // 相对模型的位置
    console.log(pointLabel)   
    skyBox.add(pointLabel); //绑定到模型

也看到了,你也可以选择直接新建一个容器、但是我尝试的时候内容无法动态变化、如果你不需要动态变化也可以直接新建 

找资料的时候看到一个问题(没有尝试)、创建的这个容器切换场景不会消失、需要注意处理、这个创建出来的不在模型列表内、而是在dom里面、所以遇到这个情况、请尝试直接处理dom

效果:

注:

前面两种方式是直接在场景内加载一个模型、第三种方式是将元素绑定在模型上

原文地址:https://www.cnblogs.com/yc-c/p/13901454.html