5

最近有Autodesk Forge的小伙伴们都在询问要怎么在 Viewer 里做到鼠标点击自定义形体或是做到鼠标移动到构件上时把他高亮,这在 viewer 里是做的到的,不过必需透过撰写一个自定义的 Tool 和扩展来启动这个自定义的 Tool 才能做到。一个基本的 Viewer Tool 长的像下面这个样子,以下示例都是使用 ES2015 的语法表示:

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语法):

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语法):

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. 鼠标点击自定义形体

// 使用鼠标点击自定义形体,并改变它的颜色
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...

以上就是本日的示例,希望对各为小夥伴们有帮助


康益昇
748 声望103 粉丝

引用和评论

0 条评论