Autodesk Forge 查看器自定义标记未在查看器上恢复

Autodesk forge viewer custom markup is not restored on viewer

我按照示例创建了自定义标记: https://forge.autodesk.com/blog/implementing-custom-markups

标记已创建、突出显示和编辑。我们保存有关文档标记的信息并将其发送到服务器。当您打开文档时,原生标记被完美还原 - 编辑、突出显示。但是自定义标记有一个问题——它们显示在文档中,但无法编辑。它们不是供查看者使用的标记。在我看来,这是因为查看者不知道自定义标记的类型(在示例中 this.type = 'smiley';)

如何解决这个问题?谢谢!

我们这样还原标记:

forgeRef.viewer.loadExtension('Autodesk.Viewing.MarkupsCore').then((m: any) => {
  setMarkup(m)
  const currentMarkup = allMarkupElements.find(item => item.page === activePage)
  if (currentMarkup) {
    m.show()
    m.loadMarkups(currentMarkup.data, 'Layer1')
    m.viewer.restoreState(currentMarkup.viewerState, undefined, true)
    if (!m.enterEditMode('Layer1')) {
      console.error('enter edit mode returns false') // eslint-disable-line
    }
  } else if (!m.enterEditMode()) {
    console.error('enter edit mode returns false') // eslint-disable-line
  }
  m.allowNavigation(true)
})

事实证明,通过重新初始化自定义标记可以解决问题。 currentMarkup.data 是一个 SVG 字符串,其中包含有关自定义标记的信息。 从这个字符串中,您需要使用解析器提取自定义标记并在没有它的情况下加载标记。然后您需要重新创建您的自定义标记。

之后,自定义标记将出现在查看器上并可以进行编辑。

  import { parse, stringify } from 'svgson'
   
  const splitLocationMarkup = async (svgData: string) => {
    const parsedSvg = await parse(svgData)
    const children = parsedSvg.children.filter(({ name }) => name !== 'metadata')
    const location = children.find(
      child => child.children[0].children[0].attributes.type === 'location'
    )

    const childrenWithoutLocation = parsedSvg.children.filter(
      child => child.children[0].children[0]?.attributes.type !== 'location'
    )
    const svgWithoutLocation = stringify({
      ...parsedSvg,
      children: childrenWithoutLocation,
    })
    return { location, svgWithoutLocation }
  }

  const initializingLocationMarkup = async (
    location: any,
    id: number | string,
    markupInstance: any
  ) => {
    if (location) {
      const locationAttributes = location.children[0].children[0].attributes
      const [positionX, positionY] = locationAttributes.position.split(' ').map(Number)
      const position = { x: positionX, y: positionY }
      const [sizeX, sizeY] = locationAttributes.size.split(' ').map(Number)
      const style = {
        'fill-color': locationAttributes['fill-color'],
        'fill-opacity': locationAttributes['fill-opacity'],
        'stroke-color': locationAttributes['stroke-color'],
        'stroke-opacity': locationAttributes['stroke-opacity'],
        'stroke-width': locationAttributes['stroke-width'],
      }
      // @ts-ignore
      const { MarkupLocation } = await import(
        '../../Viewer/CustomMarkups/LocationMarkup/location-markup'
        )
      const customLocationMarkup = new MarkupLocation(id, markupInstance.editFrame.editor)
      // @ts-ignore
      customLocationMarkup.setSize(position, sizeX, sizeY)
      // @ts-ignore
      customLocationMarkup.setStyle(style)
      markupInstance.editFrame.editor.addMarkup(customLocationMarkup)
    }
  }

  const handleDocumentLoaded = (doc: any, pages: number) => {
    setPagesCount(pages)
    if (forgeRef?.viewer) {
      forgeRef.viewer.loadExtension('Autodesk.Viewing.MarkupsCore').then(async (m: any) => {
        setMarkup(m)
        const currentMarkup = allMarkupElements.find(item => item.page === activePage)
        if (currentMarkup) {
          m.show()
          const { location, svgWithoutLocation } = await splitLocationMarkup(currentMarkup.data)
          //Loading the markups without custom markup
          m.loadMarkups(svgWithoutLocation, 'Layer1')
          //Initializing custom markup
          initializingLocationMarkup(location, 'location', m)

          m.viewer.restoreState(currentMarkup.viewerState, undefined, true)
          if (!m.enterEditMode('Layer1')) {
            console.error('enter edit mode returns false') // eslint-disable-line
          }
        } else if (!m.enterEditMode()) {
          console.error('enter edit mode returns false') // eslint-disable-line
        }
        m.allowNavigation(true)
      })
    }
  }