在我们3d的开发中,对某一些建筑和物体进行解释说明是非常常见的现象,那么就不得不说卡片的展示了,卡片展示很友好的说明了当前物体的状态,一目了然,下面就是效果图。
它主要有两个方法来实现,大量的图片建议使用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
- 将需要加入的标签加入,并创建CSS3DObject对象,
- 将css3dObject加入Scene
点击增加标签,判断是否已经存在,存在就不增加了
eventHub.on('spriteClick', (ele) => {var isCreateTag = falsefloor2Tags.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 + 10var 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 = `<div class="elementContent"><h3>实时监控${object3d.name + index}</h3><div class="elementProgress"><div class="circle_process"><div class="wrapper right"><div class="circle rightcircle" style="transform:rotate(${percent < 50 ? deg1 : 45}deg)"></div></div><div class="wrapper left"><div class="circle leftcircle" style="transform:rotate(${percent < 50 ? 'none' : deg2}deg)"></div></div><div class="wrapper_num"><p>${percent}</p><p>mg/m³</p></div></div><div class="elementPm"><p>0.094<span>TSP</span></p><p>0.044<span>PM2.5</span></p><p>0.085<span>PM10</span></p></div></div></div>`;const objectCSS3D = new CSS3DObject(element);//加载视频objectCSS3D.name = object3d.name + indexobjectCSS3D.position.set(object3d.position.x / 5 + 20,100,object3d.position.y / 5 - 10,);objectCSS3D.scale.set(0.2, 0.2, 0.2);return objectCSS3D;}
以上就是两种创建标签的方法,如果还有更好的方法可能我还没有发现,如果有兴趣交流可以私信或者留言,看到会第一时间回复,下期我们说说如何让这个卡片一直面向观察摄像头。