threejs添加弹窗

  • Post author:
  • Post category:其他




添加弹窗 效果

在这里插入图片描述



首先安排插件 creatinfobox.js (这是在vue项目的引入,其他适当调整即可)

/*
 * @Author: your name
 * @Date: 2022-01-27 10:58:22
 * @LastEditTime: 2022-02-09 17:19:34
 * @LastEditors: Please set LastEditors
 * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 * @FilePath: \branches\src\common\js\createInfoBox.js
 */

import {CSS3DRenderer, CSS3DObject, CSS3DSprite} from 'three/examples/jsm/renderers/CSS3DRenderer';
import {CSS2DRenderer, CSS2DObject} from 'three/examples/jsm/renderers/CSS2DRenderer';

export default class CreateInfoBox {
  constructor(scene, element, renderModel = 3) {
    this.renderModel = renderModel; // css的渲染的模式(2D 和 3D 模式)
    this.cssRenderer = undefined; // Renderer对象
    this.scene = scene; // Renderer对象
    this.cssRendererDomElement = undefined; // 信息框的dom对象
    // this.infoBoxLayer = new Group();// 信息框的三维物体组
    this.config = {};
    this.init(element); // 初始化
    this.dom = null;
    this.tmp = null;
  }
  init(element) {
    const cssRenderer = this.renderModel === 2 ? new CSS2DRenderer() : new CSS3DRenderer();
    cssRenderer.setSize(element.offsetWidth, element.offsetHeight);
    cssRenderer.domElement.style.position = 'absolute';
    cssRenderer.domElement.style.top = 0;
    cssRenderer.domElement.style.pointerEvents = 'none';
    element.appendChild(cssRenderer.domElement);
    this.cssRenderer = cssRenderer;
    this.cssRendererDomElement = cssRenderer.domElement;
  }

  add(option) {
    let list = [];
    if (Array.isArray(option))
      list = option;
    else
      list.push(option);
    list.forEach(e => {
      this.dom = document.createElement('div');
      this.tmp = document.createElement('div');
      this.tmp.innerHTML = e.element;
      this.dom = this.tmp.children[0];
      const label = this.renderModel === 2 ? new CSS2DObject(this.dom) : this.renderModel === 3 ? new CSS3DObject(this.dom) : new CSS3DSprite(this.dom);
      label.userData.isCss23D = true;
      label.position.set(e.position[0], e.position[1], e.position[2]);
      label.name = e.name;
      if (e.scale) label.scale.set(e.scale[0], e.scale[1], e.scale[2]);
      e.parent ? e.parent.add(label) : this.scene.add(label);
      this.config[e.name] = label;
      //再添加css3引导线
      // this.addGuideLine(e);
    });
  }
  update(name, innerHtml) {
    this.config[name].element.innerHTML = innerHtml;
  }
  remove(name, parent) {
    parent = parent || this.scene;
    parent.remove(parent.getObjectByName(name));
    if (this.config[name]) delete this.config[name];
  }
  search(name) {
    return this.config[name];
  }
  removeAll(parent) {
    //需要倒序遍历
    for (let i = parent.children.length - 1;i >= 0;i--) {
      const e = parent.children[i];
      if (e.userData.isCss23D) {
        const name = e.name;
        parent.remove(e);
        if (this.config[name]) delete this.config[name];
      }
    }
  }

}



使用

import CreateInfoBox from '../../common/createInfoBox';

        
        //下面是在mounted中声明的
    sceneContainer = document.getElementById('container'); //底图场景容器
    css2dInstance = new CreateInfoBox(scene, sceneContainer, 2);
    css2DRenderer = css2dInstance.cssRenderer;

//下面这个方法是关键
/**
     * @event: speedTips
     * @author: 大帅逼
     * @param: model 需要添加到哪个模型或场景中 scene
     * @param: html 文本
     * @param: position 相对模型坐标位置
     * @param: name 模型名称
     * @description: 高速标题弹窗创建
     * **/
    speedTips(model, html, position, name) {
      if (position) {
        const css3Group = new THREE.Group(); // 信息框的三维物体组
        css3Group.name = name;
        const scale = [10, 10, 10];
        model.add(css3Group);
        const list = [
          {
            parent: css3Group,
            name: name,
            element: html,
            scale: scale,
            position: position
          }
        ];
        css2dInstance.add(list);
      }
    }
    //使用示例  d3Projection是经纬度转平面的方法,这里要不要提供一些
       const to3dMapPointArr = d3Projection([i.lng, i.lat]);
          const modelDiv = `
            <div class="lineDiv" id="lineDiv${i.id}">
            </div>
          `;
          this.speedTips(sceneModel, modelDiv, [to3dMapPointArr[0], 270, to3dMapPointArr[1]], `lineDivS${i.id}`);




这就添加好了,一般html我们一般不在js里写,写在vue的template中,方便做数据处理,所以这里有个小技巧,可以在js代码使用上述的speedTips方法添加一个div,然后将这个div的位置信息赋给vue上写的标签

//vue
<template>
	<div id="lineBox">{{name}}</div>
</template>


const to3dMapPointArr = d3Projection([i.lng, i.lat]);
          const modelDiv = `
            <div class="lineDiv" id="lineDiv${i.id}">
            </div>
          `;
          this.speedTips(sceneModel, modelDiv, [to3dMapPointArr[0], 270, to3dMapPointArr[1]], `lineDivS${i.id}`);
document.getElementById('lineBox').style.transform = document.getElementById(`lineDiv${i.id}`).style.transform;

//然后根据需要适当调整弹框lineBox位置即可



最后交代一下这个 坐标换算 npm i d3-geo – save -dev

import * as d3 from ‘d3-geo’;

export function projection() {


const projectionPos = d3.geoMercator().center([81.23, 46.33]) // 这个不太懂百度吧,没百明白

.scale(6400)

.translate([0, 0]);

// console.log(projectionPos);

return projectionPos;

}

引入后使用

d3Projection = projection();



版权声明:本文为LBY_XK原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。