【问题标题】:How to load extensions for the Forge Viewer (without a viewerApp)如何为 Forge Viewer 加载扩展(没有 viewerApp)
【发布时间】:2019-11-20 04:44:56
【问题描述】:

我正在尝试为 Web 应用程序开发 Forge Autodesk 查看器,this tutorial。我在尝试加载 extensions 时遇到问题,实际上它们从未加载到查看器上。

我已经开发了本教程的查看器,并且扩展程序正常工作。 我的查看器和教程的查看器的主要区别在于教程中使用了viewerApp,而我必须直接使用GUIViewer3D(用于多个模型的聚合)。

我已经尝试以不同的顺序加载查看器和扩展程序,但它也没有改变。我假设扩展程序的代码是正确的,因为它在教程中有效,但我不确定我如何将它链接到我的查看器。

加载查看器的代码:

Autodesk.Viewing.Initializer(options, function onInitialized() {

    // Initialisation du Viewer
    var viewerDiv = document.getElementById('MyViewerDiv');
    var config = {
        extensions: ['DockingPanelExtension']
    };
    viewer = new Autodesk.Viewing.Private.GuiViewer3D(viewerDiv, config);
    viewer.initialize();
});

索引代码

<head>
    <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=no" />
    <meta charset="utf-8">

    <!-- The Viewer CSS -->
    <link rel="stylesheet" href="https://developer.api.autodesk.com/modelderivative/v2/viewers/6.*/style.min.css"
        type="text/css">

    <!-- Developer CSS -->
    <link rel="stylesheet" href="/static/style.css" type="text/css">

    <!-- Common packages: jQuery, Bootstrap, jsTree -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/jstree/3.3.7/jstree.min.js"></script>
    <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css">
    <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/jstree/3.3.7/themes/default/style.min.css" />

</head>

<body>

    <!-- Fixed navbar by Bootstrap: https://getbootstrap.com/examples/navbar-fixed-top/ -->
    <nav class="navbar navbar-default navbar-fixed-top">
        <div class="container-fluid">
            <ul class="nav navbar-nav left">
                <li>
                    <a href="http://developer.autodesk.com" target="_blank">
                        <img alt="IM-Pact" src="static/img/IMPact.png"
                            height="20">
                    </a>
                </li>
                <li>
                    <button type="button" class="btn btn-default navbar-btn" onClick="callNew()">Add next model</button>
                </li>
            </ul>
        </div>
    </nav>
    <!-- End of navbar -->

    <div class="container-fluid fill">
        <div class="row fill">
            <div class="col-sm-4 fill">
                <div class="panel panel-default fill">
                    <div class="panel-heading" data-toggle="tooltip">
                        Buckets &amp; Objects
                        <span id="refreshBuckets" class="glyphicon glyphicon-refresh" style="cursor: pointer"></span>
                        <button class="btn btn-xs btn-info" style="float: right" id="showFormCreateBucket"
                            data-toggle="modal" data-target="#createBucketModal">
                            <span class="glyphicon glyphicon-folder-close"></span> New bucket
                        </button>
                    </div>
                    <div id="appBuckets">
                        tree here
                    </div>
                </div>
            </div>
            <div class="col-sm-8 fill">
                <div id="MyViewerDiv"></div>
            </div>
        </div>
    </div>
    <form id="uploadFile" method='post' enctype="multipart/form-data">
        <input id="hiddenUploadField" type="file" name="theFile" style="visibility:hidden" />
    </form>
    <!-- Modal Create Bucket -->
    <div class="modal fade" id="createBucketModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
        <div class="modal-dialog" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-label="Cancel">
                        <span aria-hidden="true">&times;</span>
                    </button>
                    <h4 class="modal-title" id="myModalLabel">Create new bucket</h4>
                </div>
                <div class="modal-body">
                    <input type="text" id="newBucketKey" class="form-control"> For demonstration purposes, objects
                    (files) are
                    NOT automatically translated. After you upload, right click on
                    the object and select "Translate". Bucket keys must be of the form [-_.a-z0-9]{3,128}
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
                    <button type="button" class="btn btn-primary" id="createNewBucket">Go ahead, create the
                        bucket</button>
                </div>
            </div>
        </div>
    </div>

    <!-- <button id="MyNextButton" onClick="callNext()">Next!</button> -->

    <!-- The Viewer JS -->
    <script src="https://developer.api.autodesk.com/modelderivative/v2/viewers/viewer3D.min.js?v=v6.6"></script>

    <!-- Developer JS -->
    <script src="static/js/docLoad.js"></script>
    <script src="static/js/modelLoad.js"></script>
    <script src="static/js/extensions/dockingpannelextension.js"></script>
    <script src="static/js/viewer.js"></script>
    <script src="static/js/tree.js"></script>
</body>

扩展的代码

// *******************************************
// Model Summary Extension
// *******************************************

var propsToList = [];

function addToList(item) {
    if (propsToList.includes(item)) {
        var index = propsToList.indexOf(item);
        propsToList.splice(index, 1);
    } else {
        propsToList.push(item)
    }
    console.log(propsToList)
}

function ModelSummaryExtension(viewer, options) {
    Autodesk.Viewing.Extension.call(this, viewer, options);
    this.panel = null; // create the panel variable
}

ModelSummaryExtension.prototype = Object.create(Autodesk.Viewing.Extension.prototype);
ModelSummaryExtension.prototype.constructor = ModelSummaryExtension;

ModelSummaryExtension.prototype.load = function () {
    if (this.viewer.toolbar) {
        // Toolbar is already available, create the UI
        this.createUI();
    } else {
        // Toolbar hasn't been created yet, wait until we get notification of its creation
        this.onToolbarCreatedBinded = this.onToolbarCreated.bind(this);
        this.viewer.addEventListener(Autodesk.Viewing.TOOLBAR_CREATED_EVENT, this.onToolbarCreatedBinded);
    }
    return true;
};

ModelSummaryExtension.prototype.onToolbarCreated = function () {
    this.viewer.removeEventListener(Autodesk.Viewing.TOOLBAR_CREATED_EVENT, this.onToolbarCreatedBinded);
    this.onToolbarCreatedBinded = null;
    this.createUI();
};

ModelSummaryExtension.prototype.createUI = function () {
    var _this = this;

    // prepare to execute the button action
    var modelSummaryToolbarButton = new Autodesk.Viewing.UI.Button('runModelSummaryCode');
    modelSummaryToolbarButton.onClick = function (e) {

        // check if the panel is created or not
        if (_this.panel == null) {
            _this.panel = new ModelSummaryPanel(_this.viewer, _this.viewer.container, 'modelSummaryPanel', 'Model Summary');
        }
        // show/hide docking panel
        _this.panel.setVisible(!_this.panel.isVisible());

        // if panel is NOT visible, exit the function
        if (!_this.panel.isVisible()) return;
        // ok, it's visible, let's get the summary!

        // first, the Viewer contains all elements on the model, including
        // categories (e.g. families or part definition), so we need to enumerate
        // the leaf nodes, meaning actual instances of the model. The following
        // getAllLeafComponents function is defined at the bottom
        _this.getAllLeafComponents(function (dbIds) {

            // now for leaf components, let's get some properties
            // and count occurrences of each value.

            // get only the properties we need for the leaf dbIds
            _this.viewer.model.getBulkProperties(dbIds, propsToList, function (dbIdsProps) {

                // iterate through the elements we found
                dbIdsProps.forEach(function (item) {

                    // and iterate through each property
                    item.properties.forEach(function (itemProp) {

                        // now use the propsToList to store the count as a subarray
                        if (propsToList[itemProp.displayName] === undefined)
                            propsToList[itemProp.displayName] = {};

                        // now start counting: if first time finding it, set as 1, else +1
                        if (propsToList[itemProp.displayName][itemProp.displayValue] === undefined)
                            propsToList[itemProp.displayName][itemProp.displayValue] = 1;
                        else
                            propsToList[itemProp.displayName][itemProp.displayValue] += 1;
                    });
                });

                // now ready to show!
                // the Viewer PropertyPanel has the .addProperty that receives the name, value
                // and category, that simple! So just iterate through the list and add them
                propsToList.forEach(function (propName) {
                    if (propsToList[propName] === undefined) return;
                    Object.keys(propsToList[propName]).forEach(function (propValue) {
                        _this.panel.addProperty(
                            /*name*/
                            propValue,
                            /*value*/
                            propsToList[propName][propValue],
                            /*category*/
                            propName);
                    });
                });
            })
        })

    };
    // modelSummaryToolbarButton CSS class should be defined on your .css file
    // you may include icons, below is a sample class:
    modelSummaryToolbarButton.addClass('modelSummaryToolbarButton');
    modelSummaryToolbarButton.setToolTip('Model Summary');

    // SubToolbar
    this.subToolbar = (this.viewer.toolbar.getControl("MyAppToolbar") ?
        this.viewer.toolbar.getControl("MyAppToolbar") :
        new Autodesk.Viewing.UI.ControlGroup('MyAppToolbar'));
    this.subToolbar.addControl(modelSummaryToolbarButton);

    this.viewer.toolbar.addControl(this.subToolbar);
};

ModelSummaryExtension.prototype.unload = function () {
    this.viewer.toolbar.removeControl(this.subToolbar);
    return true;
};

ModelSummaryExtension.prototype.getAllLeafComponents = function (callback) {
    var cbCount = 0; // count pending callbacks
    var components = []; // store the results
    var tree; // the instance tree

    function getLeafComponentsRec(parent) {
        cbCount++;
        if (tree.getChildCount(parent) != 0) {
            tree.enumNodeChildren(parent, function (children) {
                getLeafComponentsRec(children);
            }, false);
        } else {
            components.push(parent);
        }
        if (--cbCount == 0) callback(components);
    }
    this.viewer.getObjectTree(function (objectTree) {
        tree = objectTree;
        var allLeafComponents = getLeafComponentsRec(tree.getRootId());
    });
};

// *******************************************
// Model Summary Panel
// *******************************************
function ModelSummaryPanel(viewer, container, id, title, options) {
    this.viewer = viewer;
    Autodesk.Viewing.UI.PropertyPanel.call(this, container, id, title, options);
}
ModelSummaryPanel.prototype = Object.create(Autodesk.Viewing.UI.PropertyPanel.prototype);
ModelSummaryPanel.prototype.constructor = ModelSummaryPanel;

Autodesk.Viewing.theExtensionManager.registerExtension('ModelSummaryExtension', ModelSummaryExtension);

提前致谢!

【问题讨论】:

    标签: javascript autodesk-forge autodesk-viewer


    【解决方案1】:

    在扩展 JavaScript 文件中,您在名称 ModelSummaryExtension 下注册扩展,但在查看器初始化代码中,您使用 extensions: ['DockingPanelExtension'] 传递配置对象。这可能是未加载扩展程序的原因。尝试使用以下配置初始化 GuiViewer3D 类:

    let config = {
        extensions: ['ModelSummaryExtension']
    };
    

    编辑(在扩展名被修复后):

    初始化GuiViewer3D 时,调用其start() 方法而不是initialize()。它将在内部调用initialize()(用于初始化内部结构、事件处理程序等)、setUp();(用于根据您的配置对象配置查看器),最后如果有 URN 或文件路径,它将调用loadModel()传递给函数的参数。

    【讨论】:

    • 感谢您的提示,确实我没有注意到这个命名错误。但是,即使命名正确,到目前为止它仍然无法正常工作。我可能知道为什么:在我构建视图的方式中,在用户单击文件树中的某些模型之前没有加载任何模型。因此,当扩展加载时,viewer.initialize() 已经执行,但没有加载模型。会不会是问题的根源?或者可能是因为我的扩展适合viewerApp objetcs 而不是GuiViewer3D
    • 除了命名不同之外,查看器初始化代码似乎还可以。看看GuiViewer3D这个类是怎么初始化的here,看看有没有区别。如果您仍然无法解决问题,我需要查看整个解决方案 - 您可以在 github 上的某个地方分享它吗?
    • 另外,不要打电话给viewer.initialize();,试试viewer.start();
    • 谢谢,viewer.start() 成功了!让我明白,initializestart 方法有什么区别?
    • start 方法基本上做了 3 件事:(1)调用.initialize() 来初始化查看器的内部结构,(2)调用.setUp() 来根据您的配置对象配置查看器传入,并且 (3) 如果提供了 URN 或文件参数,则加载模型。
    猜你喜欢
    • 2020-05-14
    • 2020-09-05
    • 2020-10-30
    • 2021-03-09
    • 2022-11-10
    • 2020-05-31
    • 2021-02-19
    • 2020-01-06
    • 2020-11-24
    相关资源
    最近更新 更多