资讯专栏INFORMATION COLUMN

在 Forge Viewer 里切换模型视图(Viewables)

BlackHole1 / 3760人阅读

摘要:有提供类似的功能,但这并不包含在里头。条列清单或是切换视图是非常容易的,你主要是要建立一个使用者介面让使用者去选取他们想观看的内容。我使用了来确保当前载入模型占用的内存可以都被释出。

此篇文章原作是 Autodesk ADN Philippe Leefsma,以下以我简称。

这有一个简易的博客用来说明一个我刚加入 https://forge-rcdb.autodesk.io 的一个新功能,他主要是提供一个使用介面让使用者可以在一个文档(Forge Document)里不同的视图(Forge Viewable)间快速的切换。A360 viewer有提供类似的功能,但这并不包含在 Forge Viewer 里头。

在 Forge Document 里。条列 Viewable 清单或是切换视图是非常容易的,你主要是要建立一个使用者介面让使用者去选取他们想观看的内容。如果您不知道要怎么让 Forge Model Derivative 服务帮您转换多个视图,请先看看这篇文章:为什么Revit模型有多个视图,丢到 Forge 转换后确只剩一个? (如何设定多个视图)

接著让我们来看看该怎么实作这个功能(我所有的代码都有用到 ES6、async/await,UI的部份使用了 React):

一、从已转换好的 URN 载入 Document:

/////////////////////////////////////////////////////////
// Load a document from URN
//
/////////////////////////////////////////////////////////
static loadDocument (urn) {

  return new Promise((resolve, reject) => {

    const paramUrn = !urn.startsWith("urn:")
      ? "urn:" + urn
      : urn

    Autodesk.Viewing.Document.load(paramUrn, (doc) => {

      resolve (doc)

    }, (error) => {

      reject (error)
    })
  })
}

二、从已载入的 Document 物件获取所有 Viewable 清单:

/////////////////////////////////////////////////////////
// Return viewables
//
/////////////////////////////////////////////////////////
static getViewableItems (doc, roles = ["3d", "2d"]) {

  const rootItem = doc.getRootItem()

  let items = []

  const roleArray = roles
    ? (Array.isArray(roles) ? roles : [roles])
    : []

  roleArray.forEach((role) => {

    items = [ ...items,
      ...Autodesk.Viewing.Document.getSubItemsWithProperties(
        rootItem, { type: "geometry", role }, true) ]
  })

  return items
}

三、载入已选中的 Viewable:
首先,我门要把已载入的模型先卸载,下面的样例是假设我们已经载入了一个模型,现在使用者选择了新的 Viewable
要 Forge Viewer 载入。我使用了 viewer.tearDown() 来确保当前载入模型占用的内存可以都被释出。这个样例也支持从 3D 模型切换到 2D 模型,或者是反过来;您可以忽略我代码里使用到的 React 相关的代码。

/////////////////////////////////////////////////////////
// Load the selected viewable
//
/////////////////////////////////////////////////////////
onItemSelected (item) {

  const {activeItem} = this.react.getState()

  if (item.guid !== activeItem.guid) {

    this.viewer.tearDown()

    this.viewer.start()

    const path =
      this.viewerDocument.getViewablePath(item)

    this.viewer.loadModel(path)

    this.react.setState({
      activeItem: item
    })
  }
}

完整的代码如下所示,对这功能有兴趣的朋友们可以通过这个网址 https://forge-rcdb.autodesk.i...,并载入 Viewable Selector 来体验。

/////////////////////////////////////////////////////////
// Viewing.Extension.ViewableSelector
// by Philippe Leefsma, November 2017
//
/////////////////////////////////////////////////////////
import MultiModelExtensionBase from "Viewer.MultiModelExtensionBase"
import "./Viewing.Extension.ViewableSelector.scss"
import WidgetContainer from "WidgetContainer"
import ReactTooltip from "react-tooltip"
import ServiceManager from "SvcManager"
import Toolkit from "Viewer.Toolkit"
import ReactDOM from "react-dom"
import Image from "Image"
import Label from "Label"
import React from "react"

class ViewableSelectorExtension extends MultiModelExtensionBase {

  /////////////////////////////////////////////////////////
  // Class constructor
  //
  /////////////////////////////////////////////////////////
  constructor (viewer, options) {

    super (viewer, options)

    this.react = options.react
  }

  /////////////////////////////////////////////////////////
  //
  //
  /////////////////////////////////////////////////////////
  get className() {

    return "viewable-selector"
  }

  /////////////////////////////////////////////////////////
  // Extension Id
  //
  /////////////////////////////////////////////////////////
  static get ExtensionId() {

    return "Viewing.Extension.ViewableSelector"
  }

  /////////////////////////////////////////////////////////
  // Load callback
  //
  /////////////////////////////////////////////////////////
  load () {

    this.react.setState({

      activeItem: null,
      items: []

    }).then (async() => {

      const urn = this.options.model.urn

      this.viewerDocument =
        await this.options.loadDocument(urn)

      const items =
        await Toolkit.getViewableItems(
          this.viewerDocument)

      if (items.length > 1) {

        this.createButton()

        await this.react.setState({
          activeItem: items[0],
          items: [items[0], items[1], items[2]]
        })

        if (this.options.showPanel) {

          this.showPanel (true)
        }
      }
    })

    console.log("Viewing.Extension.ViewableSelector loaded")

    return true
  }

  /////////////////////////////////////////////////////////
  // Unload callback
  //
  /////////////////////////////////////////////////////////
  unload () {

    this.react.popViewerPanel(this)

    console.log("Viewing.Extension.ViewableSelector unloaded")

    return true
  }

  /////////////////////////////////////////////////////////
  // Load the selected viewable
  //
  /////////////////////////////////////////////////////////
  onItemSelected (item) {

    const {activeItem} = this.react.getState()

    if (item.guid !== activeItem.guid) {

      this.viewer.tearDown()

      this.viewer.start()

      const path =
        this.viewerDocument.getViewablePath(item)

      this.viewer.loadModel(path)

      this.react.setState({
        activeItem: item
      })
    }
  }

  /////////////////////////////////////////////////////////
  // Create a button to display the panel
  //
  /////////////////////////////////////////////////////////
  createButton () {

    this.button = document.createElement("button")

    this.button.title = "This model has multiple views ..."

    this.button.className = "viewable-selector btn"

    this.button.innerHTML = "Views"

    this.button.onclick = () => {

      this.showPanel(true)
    }

    const span = document.createElement("span")

    span.className = "fa fa-list-ul"

    this.button.appendChild(span)

    this.viewer.container.appendChild(this.button)
  }

  /////////////////////////////////////////////////////////
  // Show/Hide panel
  //
  /////////////////////////////////////////////////////////
  showPanel (show) {

    if (show) {

      const {items} = this.react.getState()

      this.button.classList.add("active")

      const container = this.viewer.container

      const height = Math.min(
        container.offsetHeight - 110,
        (items.length + 1)  * 78 + 55)

      this.react.pushViewerPanel(this, {
        maxHeight: height,
        draggable: false,
        maxWidth: 500,
        minWidth: 310,
        width: 310,
        top: 30,
        height
      })

    } else {

      this.react.popViewerPanel(this.id).then(() => {

        this.button.classList.remove("active")
      })
    }
  }

  /////////////////////////////////////////////////////////
  // Render React panel content
  //
  /////////////////////////////////////////////////////////
  renderContent () {

    const {activeItem, items} = this.react.getState()

    const urn = this.options.model.urn

    const apiUrl = this.options.apiUrl

    const domItems = items.map((item) => {

      const active = (item.guid === activeItem.guid)
        ? " active" :""

      const query = `size=400&guid=${item.guid}`

      const src = `${apiUrl}/thumbnails/${urn}?${query}`

      return (
        
this.onItemSelected(item)}>
) }) return (
{domItems}
) } ///////////////////////////////////////////////////////// // Render title // ///////////////////////////////////////////////////////// renderTitle () { return (
) } ///////////////////////////////////////////////////////// // Render main // ///////////////////////////////////////////////////////// render (opts) { return ( this.renderTitle(opts.docked)} showTitle={opts.showTitle} className={this.className}> {this.renderContent()} ) } } Autodesk.Viewing.theExtensionManager.registerExtension( ViewableSelectorExtension.ExtensionId, ViewableSelectorExtension)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/89898.html

相关文章

  • 使用 Forge Viewer 序列中聚合多模型

    摘要:但模型载入程序并不是同步执行的载入文档和几何等动作在里都是异步的,我们没办法知道哪一个模型是第一个被完整载入,和下个一个完全载入的是谁而在一些应用场景里是有可能需要在一个序列聚合多个模型。 showImg(https://segmentfault.com/img/bVVaPI?w=600&h=390); 此篇博客原著为 Autodesk ADN 的梁晓冬,以下以我简称。 我的同事创作了...

    graf 评论0 收藏0
  • Revit 重现 Forge Viewer相机的状态

    摘要:最近,我收到一个客户的需求,希望可以把的相机状态通过还原到里。因为没有直接的方法可以修改相机的值。的相机视角比的相机视角宽。调用以取得焦距。因此,裁剪区域的范围计算为宽度视图的相机焦距。高度常规相机片幅的比例。 最近,我收到一个客户的需求,希望可以把Viewer的相机状态通过Revit API还原到Revit里。所以我们来看看要如何实现这个要求。在开始之前,你要先知道一些有关于Revi...

    刘福 评论0 收藏0
  • Forge Viewer 显示 Revit 格子线 (grids)

    最近一些Forge客户都在询问我同一个的问题,他们希望将Revit的网格呈现在viewer中,藉此让我有机会来完成这件事,并将它记录在本文章里,就让我们开始吧! 在开始之前,有件事你必须先知道: 由于在Revit里格子线只能在2D视图(例如平面图、立面图、表单等等)中显示,并不会在3D视图中被看见。因此,我们也无法在ForgeViewer的3D视图中看到这些格子线,网格会在模型转文件时被忽略。据我...

    Yangyang 评论0 收藏0
  • Autodesk Forge Viewer 信息本地化技术分析

    摘要:默认情况下,是英文环境,调取的是的资源其实无需翻译。但是,如前面提到的,语言包只是包含了部分常规字串的翻译,如果遇到没有包含的常规字串怎么办呢例如,本例中的语言包并没有对,进行翻译,所以即使切换了语言,它们仍旧是英文。 注:本文是个人调试分析所得,非官方文档,请酌情选用参考。文中分析的数据由https://extract.autodesk.io转换下载而来。 谈到信息本地化,个人觉得包...

    littleGrow 评论0 收藏0
  • 「翻译」Forge Viewer上实作简易的模型版本比较

    摘要:现在让我们修改这个示例让他可以展示两个同项目但不同版号的模型及。示例执行结果如下这边是这个比较模型的括展代码英文原文 showImg(https://segmentfault.com/img/bVOmjp?w=1542&h=925); 熟悉 BIM360 Team 的朋友可能知道他有一个很牛的模型文档版本比较的功能,但如果模型是放在 Google 云盘或是百度云盘上有可能做到吗? Au...

    JowayYoung 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<