需求:
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
效果:
注:
前面两种方式是直接在场景内加载一个模型、第三种方式是将元素绑定在模型上