DockingPanel

2022-2-18
/**
 * 创建forge UI 面板
 * https://forge.autodesk.com/en/docs/viewer/v2/reference/javascript/dockingpanel/
 * @param {HTMLElement} parentContainer             挂载到目标节点的位置
 * @param {String} id                               容器id
 * @param {String} title                            容器名称
 * @param {HTMLElement} content                     容器内容
 * @param {Object} position                         容器位置
 * @param {Number} containerWidth                   容器默认宽度
 * @param {Number} containerWidth                   容器默认高度
 * @param {Number} containerMinWidth                容器最小宽度
 * @param {Number} containerMinHeight               容器最小高度
 * @param {Object} viewer                           模型对象实例
 * @param {String} scrollBodyClassName
 * @param {Function} afterCloseCallback             关闭后的回调
 * @param {Function} footerResizeCallback           panel放大缩小后回调
 * @param {Object} options                          附加参数
 */

class CustomDockingPanel extends window.Autodesk.Viewing.UI.DockingPanel {
  constructor({
    parentContainer,
    id,
    title,
    content,
    position = {
      top: 0,
      right: 0,
      bottom: 0,
      left: 0,
    },
    containerHeight,
    containerWidth,
    containerMinWidth = 320,
    containerMinHeight = 300,
    viewer,
    scrollBodyClassName,
    afterCloseCallback = () => {},
    footerResizeCallback = () => {},
    options,
  }) {
    super(parentContainer, id, title, options);

    this.viewer = viewer;
    this.content = content;
    this.panelTitle = title;
    this.containerWidth = containerWidth;
    this.containerHeight = containerHeight;
    this.containerMinWidth = containerMinWidth;
    this.containerMinHeight = containerMinHeight;
    this.scrollBodyClassName = scrollBodyClassName || 'scrollBody';
    this.afterCloseCallback = afterCloseCallback;
    this.footerResizeCallback = footerResizeCallback;

    // 保持滚动条
    this.overrideBringToFront = function () {
      const oldBringToFront = this.bringToFront;
      this.bringToFront = function (...args) {
        const viewpointTree = this.container?.querySelector(`.${this.scrollBodyClassName}`);
        const oldScrollTop = viewpointTree?.scrollTop || 0;

        oldBringToFront.apply(this, args);
        if (viewpointTree) viewpointTree.scrollTop = oldScrollTop;
      };
    };

    // Auto-fit to the content and don't allow resize.  Position at the coordinates given.
    this.container.style.height = `${this.containerHeight}px`;
    this.container.style.width = `${this.containerWidth}px`;
    this.container.style.minHeight = `${this.containerMinHeight}px`;
    this.container.style.minWidth = `${this.containerMinWidth}px`;
    this.container.style.backgroundColor = '#ffffff';
    // this.container.style.resize = 'none';
    this.container.style.left = `${isNaN(position.left) ? position.left : position.left + 'px'}`;
    this.container.style.top = `${isNaN(position.top) ? position.top : position.top + 'px'}`;
    this.container.style.bottom = `${
      isNaN(position.bottom) ? position.bottom : position.bottom + 'px'
    }`;
    this.container.style.right = `${
      isNaN(position.right) ? position.right : position.right + 'px'
    }`;
  }

  // listenerWindowResize() {
  //  setTimeout(() => {
  //    const { offsetWidth, offsetHeight } = this.viewer && this.viewer.canvasWrap;
  //    let [resultWidth, resultHeight] = [0, 0];

  //    resultWidth = this.containerMinWidth > offsetWidth ? offsetWidth : this.containerMinWidth;
  //    resultHeight =
  //      this.containerMinHeight > offsetHeight ? offsetHeight - 100 : this.containerMinHeight;

  //    this.container.style.minWidth = `${resultWidth}px`;
  //    this.container.style.minHeight = `${resultHeight}px`;
  //  });
  // }

  initialize() {
    setTimeout(() => {
      // Override DockingPanel initialize() to:
      // - create a standard title bar
      // - click anywhere on the panel to move
      // - create a close element at the bottom right
      let dragFlag = false;
      // const listenerWindowResize = this.listenerWindowResize.bind(this);
      const handleDocumentMouseUp = () => {
        if (dragFlag) {
          const scrollWrapBody =
            this.scrollBodyClassName && document.querySelector(`.${this.scrollBodyClassName}`);
          dragFlag = false;

          // this.resizeToContent();
          this.footerResizeCallback(scrollWrapBody);
        }
      };
      const handleresizeFooterMouseDown = () => {
        dragFlag = true;
      };

      this.title = this.createTitleBar(this.panelTitle || this.container.id);
      // this.title.style.borderBottom = 0;
      this.container.appendChild(this.title);
      this.scrollContainer = this.createScrollContainer();
      this.scrollContainer.appendChild(this.content);
      // this.container.appendChild(this.scrollContainer);
      this.initializeMoveHandlers(this.title);

      // this.closer = document.createElement('div');
      // this.closer.className = 'simplePanelClose';
      // this.closer.textContent = 'Close';
      this.closer = this.createCloseButton();
      this.initializeCloseHandler(this.closer);
      this.container.appendChild(this.closer);

      // window.addEventListener('resize', listenerWindowResize, false);
      // listenerWindowResize();

      if (this.options.addFooter) {
        this.footer = this.createFooter();
        this.container.appendChild(this.footer);
      }

      const resizeFooter =
        this.footer && this.footer.querySelector('.docking-panel-footer-resizer');
      if (resizeFooter) {
        resizeFooter.addEventListener('mousedown', handleresizeFooterMouseDown, false);
        document.addEventListener('mouseup', handleDocumentMouseUp, false);
      }

      // 关闭后的回调
      this.addVisibilityListener(() => {
        setTimeout(() => {
          const isVisible = this.isVisible();
          !isVisible && this.afterCloseCallback();

          // window.removeEventListener('resize', listenerWindowResize);
          document.removeEventListener('mouseup', handleDocumentMouseUp);
          resizeFooter &&
            resizeFooter.removeEventListener('mousedown', handleresizeFooterMouseDown);
        });
      });

      this.resizeToContent();
      this.overrideBringToFront();
    });
  }
}

export default CustomDockingPanel;