自定義 Viewer Tool 與 Viewer 交互

最近有Autodesk Forge的小夥伴們都在詢問要怎麼在 Viewer 裏作到鼠標點擊自定義形體或是作到鼠標移動到構件上時把他高亮,這在 viewer 裏是作的到的,不過必需透過撰寫一個自定義的 Tool 和擴展來啓動這個自定義的 Tool 才能作到。一個基本的 Viewer Tool 長的像下面這個樣子,如下示例都是使用 ES2015 的語法表示:html

class CustomTool {
  constructor( viewer ) {
    this._viewer = viewer;
    this._active = false;
    this._names = [ 'CustomTool' ];
  }

  get viewer() {
    return this._viewer;
  }

  isActive() {
    return this._active;
  }

  getNames() {
    return this._names;
  }

  getName() {
    return this._names[0];
  }

  register() {
  }

  deregister() {
  }

  activate( name ) {
    this._active = true;
  }

  update( highResTimestamp ) {
    return false;
  }

  handleSingleClick( event, button ) {
    return true;
  }

  handleDoubleClick( event, button ) {
    return false;
  }

  handleSingleTap( event, button ) {
    return false;
  }

  handleDoubleTap( event, button ) {
    return false;
  }

  handleKeyDown( event, button ) {
    return false;
  }

  handleKeyUp( event, button ) {
    return false;
  }

  handleWheelInput( event, button ) {
    return false;
  }

  handleButtonDown( event, button ) {
    return false;
  }

  handleButtonUp( event, button ) {
    return false;
  }

  handleMouseMove( event, button ) {
    return false;
  }

  handleGesture( event, button ) {
    return false;
  }

  handleBlur( event, button ) {
    return false;
  }

  handleResize( event, button ) {
    return false;
  }
}

定義完自定義 Tool 後,還必須撰寫一個擴展將這個 Tool 註冊到 viewer.toolController 裏,並透過 viewer.toolController 來啓動這個 Tool,而這個擴展現例像下面這個樣子(ES2015語法):canvas

class CustomToolExtension extends Autodesk.Viewing.Extension {
  constructor( viewer, options ) {
    super( viewer, options );
    this._tool = undefined;
  }

  load() {
    // 產生自定 Tool 實體
    this._tool = new CustomTool( this.viewer );
    // 註冊自定 Tool 到 viewer.toolController 裏
    this.viewer.toolController.registerTool( this._tool );
    // 透過 viewer.toolController 啓動自定 Tool
    this.viewer.toolController.activateTool( 'CustomTool' );

    return true;
  }

  unload() {
    // 若是自定 Tool 有被啓動的話,中止這個自定 Tool
    if( this._tool.isActive() ) {
      this.viewer.toolController.deactivateTool( 'CustomTool' );
    }
    // 取消註冊自定 Tool 
    this.viewer.toolController.deregisterTool( this._tool );
    
    return true;
  }
}

Autodesk.Viewing.theExtensionManager.registerExtension( 'Autodesk.ADN.Sample.CustomToolExtension', CustomToolExtension );

基本上到這邊就已經完成自定義 Tool 的宣告及載入方式,但要怎麼作到上面講到的使用鼠標點擊自定義形體或是作到鼠標移動到構件上時把他高亮?這個很容易,只要在自定義 Tool 的 handle 開頭的函數裏寫上自個的代碼邏輯就能夠完成了,可是要怎麼作呢?小夥伴們能夠參考下面這些示例(ES2015語法):api

1. 鼠標移動到構件上時把他高亮函數

// 鼠標移動到構件時高亮構件
handleMouseMove( event, button ) {
    const result = this.viewer.impl.hitTest( event.canvasX, event.canvasY, false );
    if( result ) {
        const dbId = result.dbId;
        // 高亮當前鼠標指到的構件
        this.viewer.impl.highlightObjectNode( _viewer.model, dbId, true, false );

        // 取消先前鼠標指到的構件的高亮
        if( this.oldDbId )
            this.viewer.impl.highlightObjectNode( _viewer.model, dbId, false, false );    
        
        this.oldDbId = dbId;
    }
    return false;
}

2. 鼠標點擊自定義形體this

// 使用鼠標點擊自定義形體,並改變它的顏色
handleSingleClick( event, button ) {
  const _viewer = this.viewer;
  const intersectObjects = (function () {
    const pointerVector = new THREE.Vector3();
    const pointerDir = new THREE.Vector3();
    const ray = new THREE.Raycaster();
    const camera = _viewer.impl.camera;

    return function(pointer, objects, recursive) {
        const rect = _viewer.impl.canvas.getBoundingClientRect();
        const x = (( pointer.clientX - rect.left) / rect.width ) * 2 - 1;
        const y = - (( pointer.clientY - rect.top) / rect.height ) * 2 + 1;
        
        if (camera.isPerspective) {
            pointerVector.set( x, y, 0.5 );
            pointerVector.unproject( camera );
            ray.set( camera.position, pointerVector.sub( camera.position ).normalize() );
        } else {
            pointerVector.set( x, y, -1 );
            pointerVector.unproject( camera );
            pointerDir.set( 0, 0, -1 );
            ray.set( pointerVector, pointerDir.transformDirection( camera.matrixWorld ) );
        }

        const intersections = ray.intersectObjects( objects, recursive );
        return intersections[0] ? intersections[0] : null;
    };
  })();

  const pointer = event.pointers ? event.pointers[ 0 ] : event;
  // 在自定形體的 Scene 裏面找到與鼠標點擊的點位有交集的自定形體
  const result = intersectObjects( pointer, myCustomShapScene.children );

  if( result && result.object ) {
    const mesh = result.object;
    // 改變形體顏色
    let curColor = mesh.material.color;
    curColor = ( curColor.getHex() == 0xff0000 ? 0x00ff00 : 0xff0000 );
    mesh.material.color.setHex( curColor );
    
    // 刷新畫面
    this.viewer.impl.invalidate( false, true, true );
  }

  return false;
}

參考:https://forge.autodesk.com/cl...code

以上就是本日的示例,但願對各爲小夥伴們有幫助orm

相關文章
相關標籤/搜索