在我们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
点击增加标签,判断是否已经存在,存在就不增加了
- 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 = `
- <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 + 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;}
以上就是两种创建标签的方法,如果还有更好的方法可能我还没有发现,如果有兴趣交流可以私信或者留言,看到会第一时间回复,下期我们说说如何让这个卡片一直面向观察摄像头。