1

最近有 Autodesk Forge 的小伙伴们都在询问要怎么在 Viewer 里显示自订义属性,要做到这个是挺容易的。目前有两种方式可以做到这个效果,一种是直接添加自定属性到 Viewer 自带的属性面板上,另一种是使用自定义属性面板,其作法如下所示:

一、添加自定属性到 Viewer 自带的属性面板上:

  1. 要添加自定义属性到自带的属性面板上前必需先获取属性面板的实体:

    const propPanel = viewer.getPropertyPanel( true );
  2. 透过 propPanel.addProperty() 添加自订义属性,例如:

    propPanel.addProperty( '所属房名', '课厅', '其他' );
  3. 一般我们不会这样直接调用这些方法,而是将它写到一个 Viewer 扩展里,其范例如下 (使用 ES2017 的语法):

    class CustomProperyPanelExt extends Autodesk.Viewing.Extension {
        constructor( viewer, options ) {
            super( viewer, options );
            
            this.onSelectionChanged = this.onSelectionChanged.bind( this );
        }
        
        getRemoteProps( dbId ) {
            return new Promise(( resolve, reject ) => {
                fetch( `http://127.0.0.1/api/props/${ dbId }`, {
                    method: 'get',
                    headers: new Headers({
                        'Content-Type': 'application/json'
                    })
                })
                .then( ( response ) => {
                    if( response.status === 200 ) {
                      return response.json();
                    } else {
                      return reject( new Error( response.statusText ) );
                    }
                })
                .then( ( data ) => {
                   if( !data ) return reject( new Error( '无法从服务器获取属性' ) );
                
                   return resolve( data );
                })
                .catch( ( error ) => reject( new Error( error ) ) );
            });
        }
        
        async onSelectionChanged( event ) {
            if( !event.selections || event.selections.length <= 0
                || !event.selections[0].dbIdArray
                || event.selections[0].dbIdArray.length <= 0 ) return;
            
            const dbId = event.selections[0].dbIdArray[0];
            const propPanel = this.viewer.getPropertyPanel( true );
            
            try {
              const props = await this.getRemoteProps( dbId );
    
              for( let i = 0; i < props.length; i++ ) {
                  const prop = props[i];
                  propPanel.addProperty( prop.name, prop.value, prop.category );
              }
            } catch( error ) {
                console.error( 
            }
        }
        
        load() {
            this.viewer.addEventListener(
                Autodesk.Viewing.AGGREGATE_SELECTION_CHANGED_EVENT,
                this.onSelectionChanged
            );
            return true;
        }
        
        unload() {
            this.viewer.removeEventListener(
                Autodesk.Viewing.AGGREGATE_SELECTION_CHANGED_EVENT,
                this.onSelectionChanged
            );
            return true;
        }
    }
    Autodesk.Viewing.theExtensionManager.registerExtension( 'Autodesk.ADN.CustomPropsPanel', CustomProperyPanelExt );

二、使用自定义属性面板

  1. 使用这个方法是创建一个自定义的属性面板,并透过 viewer.setPropertyPanel() 取代Viewer 自带的属性面板。
  2. 在来我们透过继承 Autodesk.Viewing.Extensions.ViewerPropertyPanel 来创建自个的属性面板(使用 ES2017 的语法,部份代码来自 Forge Viewer 的 viewer3D.js):

    class CustomPropsPanel extends Autodesk.Viewing.Extensions.ViewerPropertyPanel {
        constructor( viewer ) {
            super( viewer );
        }
        
        getRemoteProps( dbId ) {
            return new Promise(( resolve, reject ) => {
                fetch( `http://127.0.0.1/api/props/${ dbId }`, {
                    method: 'get',
                    headers: new Headers({
                        'Content-Type': 'application/json'
                    })
                })
                .then( ( response ) => {
                    if( response.status === 200 ) {
                      return response.json();
                    } else {
                      return reject( new Error( response.statusText ) );
                    }
                })
                .then( ( data ) => {
                   if( !data ) return reject( new Error( '无法从服务器获取属性' ) );
                
                   return resolve( data );
                })
                .catch( ( error ) => reject( new Error( error ) ) );
            });
        }
        
        async setNodeProperties( dbId ) {
            this.propertyNodeId = dbId;
            
            if( !this.viewer ) return;
            
            try {
                const reuslt = await this.getRemoteProps( dbId );
    
                this.setTitle( reuslt.Name, { localizeTitle: true } );
                this.setProperties( reuslt.properties );
                this.highlight( this.viewer.searchText );
        
                this.resizeToContent();
        
                if( this.isVisible() ) {
                    const toolController = this.viewer.toolController,
                    mx = toolController.lastClickX,
                    my = toolController.lastClickY,
                    panelRect = this.container.getBoundingClientRect(),
                    px = panelRect.left,
                    py = panelRect.top,
                    pw = panelRect.width,
                    ph = panelRect.height,
                    canvasRect = this.viewer.canvas.getBoundingClientRect(),
                    cx = canvasRect.left,
                    cy = canvasRect.top,
                    cw = canvasRect.width,
                    ch = canvasRect.height;
            
                    if( (px <= mx && mx < px + pw) && (py <= my && my < py + ph) ) {
                        if( (mx < px + (pw / 2)) && (mx + pw) < (cx + cw) ) {
                           this.container.style.left = Math.round( mx - cx ) + 'px';
                           this.container.dockRight = false;
                        } else if( cx <= (mx - pw) ) {
                           this.container.style.left = Math.round( mx - cx - pw ) + 'px';
                           this.container.dockRight = false;
                        } else if( (mx + pw) < (cx + cw) ) {
                           this.container.style.left = Math.round( mx - cx ) + 'px';
                           this.container.dockRight = false;
                        } else if( (my + ph) < (cy + ch) ) {
                           this.container.style.top = Math.round( my - cy ) + 'px';
                           this.container.dockBottom = false;
                        } else if( cy <= (my - ph) ) {
                           this.container.style.top = Math.round( my - cy - ph ) + 'px';
                           this.container.dockBottom = false;
                        }
                   }
              }
           } catch( error ) {
               this.showDefaultProperties();
           }
        }
    }
  3. 透过撰写括展让自定义属性窗取代自带的:

    class CustomProperyPanelExt extends Autodesk.Viewing.Extension {
        constructor( viewer, options ) {
            super( viewer, options );
        }
    
        load() {
            this.viewer.setPropertyPanel( new CustomPropsPanel( viewer ) );
            return true;
        }
        
        unload() {
            return true;
        }
    }
    Autodesk.Viewing.theExtensionManager.registerExtension( 'Autodesk.ADN.CustomPropsPanel', CustomProperyPanelExt );

以上希望对各为小伙伴有帮助~

参考:https://github.com/Autodesk-F...


康益昇
748 声望103 粉丝