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


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

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

    1.canvas

    思路:

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

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

    实现代码

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

    2.div标签

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

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

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

    1. eventHub.on('spriteClick', (ele) => {
    2.       var isCreateTag = false
    3.       floor2Tags.forEach(p => {
    4.         if (p.name == (ele.event.name + ele.i)) {
    5.           isCreateTag = true
    6.         }
    7.       })
    8.       if (!isCreateTag) {
    9.         const css3dObject = createTag(ele.event, ele.i);
    10.         css3dObject.visible = true;
    11.         floor2Tags.push(css3dObject)
    12.         scene.add(css3dObject)
    13.       }
    14.     })

    创建标签

    1. //添加标签和视频
    2. function createTag (object3d, index) {
    3.   // 创建各个区域的元素
    4.   const element = document.createElement("div");
    5.   var perNum = index * 10 + 10
    6.   var percent = Math.ceil((perNum / 100) * 100);
    7.   var deg1 = ((45 + 135) * percent) / 50 - 135;
    8.   var deg2 = ((45 + 135) * (percent - 50)) / 50 - 135;
    9.   element.className = "elementTag";
    10.   element.innerHTML = `
    11.     <div class="elementContent">
    12.       <h3>实时监控${object3d.name + index}</h3>
    13.       <div class="elementProgress">
    14.       <div class="circle_process">
    15.         <div class="wrapper right">
    16.             <div class="circle rightcircle" style="transform:rotate(${percent < 50 ? deg1 : 45}deg)"></div>
    17.         </div>
    18.         <div class="wrapper left">
    19.             <div class="circle leftcircle" style="transform:rotate(${percent < 50 ? 'none' : deg2}deg)"></div>
    20.         </div>
    21.         <div class="wrapper_num">
    22.           <p>${percent}</p>
    23.           <p>mg/</p>
    24.         </div>
    25.       </div>
    26.         <div class="elementPm">
    27.           <p>0.094<span>TSP</span></p>
    28.           <p>0.044<span>PM2.5</span></p>
    29.           <p>0.085<span>PM10</span></p>
    30.         </div>
    31.       </div>
    32.     </div>
    33.   `;
    34.   const objectCSS3D = new CSS3DObject(element);
    35.   //加载视频
    36.   objectCSS3D.name = object3d.name + index
    37.   objectCSS3D.position.set(
    38.     object3d.position.x / 5 + 20,
    39.     100,
    40.     object3d.position.y / 5 - 10,
    41.   );
    42.   objectCSS3D.scale.set(0.2, 0.2, 0.2);
    43.   return objectCSS3D;}

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

  • 相关阅读:
    vue-admin-better前端页面-菜单-权限配置
    SSM-Spring-day3 AOP、事务管理
    1:蓝桥杯打题
    OpenCV中initUndistortRectifyMap ()函数与十四讲中去畸变公式的区别探究
    删除 Windows Server IIS 10 和 ASP.NET 中的 HTTP 响应标头
    Ubuntu 20.04中docker-compose部署Nightingale
    力扣:103. 二叉树的锯齿形层序遍历(Python3)
    在el-table-column使用if的方法,以及出现表格错乱的解决办法
    .NET 直连SAP HANA数据库
    数字 IC 验证(1)UVM 验证技术
  • 原文地址:https://blog.csdn.net/qq_43185384/article/details/133377154