markupIcon(添加标记点)

2022-2-18
// import Toolkit from './Viewer.Toolkit';
import { debounce } from 'lodash';
import { nanoid } from 'nanoid';

const markupICON = require('@/assets/modelTool/docMan/docManMarkup.svg');

/**
 * 模型构件添加标记
 */
class ModelComponentMarkup {
  constructor(viewer) {
    this.viewer = viewer;
    this.offsetLeft = viewer.container.offsetLeft || 0;
    this.offsetTop = viewer.container.offsetTop || 0;
  }

  static exitMarkup = () => {
    let markupWrap = document.querySelector('#markupWrap');
    if (markupWrap) {
      let markUpList = markupWrap.querySelectorAll('.markupTag');
      Array.from(markUpList).forEach(el => {
        el.parentNode.removeChild(el);
      });
    }
  };

  initMarkupWrap() {
    let markupWrap = document.querySelector('#markupWrap');
    if (!markupWrap) {
      let markupWrap = document.createElement('div');
      markupWrap.id = 'markupWrap';

      this.viewer.container.appendChild(markupWrap);
    }
  }

  getHitTest(e) {
    return new Promise((resolve, reject) => {
      let clientX = e.clientX,
        clientY = e.clientY;

      let hitTest = this.viewer.clientToWorld(clientX, clientY, true);
      if (hitTest) {
        resolve(hitTest);
      }
      reject(null);
    });
  }

  // normalize
  normalize = t => {
    let e = this.viewer.navigation.getScreenViewport(),
      n = {
        x: (t.x - e.left) / e.width,
        y: (t.y - e.top) / e.height,
      };
    return n;
  };

  // getHitData
  getHitData = (t, e) => {
    (e = 1 - e), (t = 2 * t - 1), (e = 2 * e - 1);
    let n = new window.THREE.Vector3(t, e, 1),
      r = this.viewer.impl.hitTestViewport(n, !1);
    return r ? r : null;
  };

  // checkOcclusion
  checkOcclusion = (startPoint, worldPoint) => {
    let t = this.normalize({
        x: startPoint.x + this.offsetLeft,
        y: startPoint.y + this.offsetTop,
      }),
      e = this.getHitData(t.x, t.y);

    if (e) {
      // if (e.dbId)
      //   return !0;
      // var n = this.pinMarker.getWorldPoint()
      let n = worldPoint,
        r = {
          x: e.intersectPoint.x - n.x,
          y: e.intersectPoint.y - n.y,
          z: e.intersectPoint.z - n.z,
        },
        i = r.x * r.x + r.y * r.y + r.z * r.z;
      if (i > 25) return !0;
    }
    return !1;
  };

  // 相机change
  handleCameraChange = debounce(async () => {
    // const { far } = e.camera;
    const myMarkupWrap = this.viewer.container.querySelector('#markupWrap');
    const markupList = myMarkupWrap.querySelectorAll('.markupTag');

    [...markupList].forEach(el => {
      const pushpinModelPt = JSON.parse(el.dataset.hittestpoint);
      const screenpoint = this.viewer.worldToClient(
        new window.THREE.Vector3(pushpinModelPt.x, pushpinModelPt.y, pushpinModelPt.z)
      );

      el.style.left = `${screenpoint.x}px`;
      el.style.top = `${screenpoint.y}px`;

      // 开启后随着相机的视角改变,标记会跟随显示或隐藏
      // let checkOcclusion = this.checkOcclusion(screenpoint, pushpinModelPt);
      // el.style.visibility = checkOcclusion ? 'hidden' : 'visible';
    });
  }, 20);

  createMarkUp = async ({ screenPoint, worldPoint, fileCount, dbIdArray, markupOnclick }) => {
    const div = document.createElement('div');
    const markupWrapH = 30;
    const markupWrapW = 30;

    div.style.width = `${markupWrapW}px`;
    div.style.height = `${markupWrapH}px`;
    div.style.color = '#ffffff';
    div.style.position = 'absolute';
    // div.style.left = `${screenPoint.x + radomNum}px`;
    div.style.left = `${screenPoint.x}px`;
    div.style.top = `${screenPoint.y}px`;
    div.style.background = `url(${markupICON}) center center no-repeat`;
    div.style.display = 'flex';
    div.style.justifyContent = 'center';
    div.style.alignItems = 'start';
    div.innerText = fileCount;
    div.className = `markupTag ${nanoid()}`;
    div.setAttribute('data-dbid', dbIdArray.join(','));
    div.setAttribute('data-hittestpoint', JSON.stringify(worldPoint));
    div.onclick = () => markupOnclick(dbIdArray);

    return div;
  };

  async restoreState({ screenPoint, worldPoint, fileCount = 0, dbIdArray, markupOnclick }) {
    let markupWrap = document.querySelector('#markupWrap');
    if (markupWrap) {
      const singleMarkup = await this.createMarkUp({
        screenPoint,
        worldPoint,
        fileCount,
        dbIdArray,
        markupOnclick,
      });
      markupWrap.appendChild(singleMarkup);

      this.viewer.addEventListener(
        window.Autodesk.Viewing.CAMERA_CHANGE_EVENT,
        this.handleCameraChange
      );
    }
  }
}

export default ModelComponentMarkup;