I created a custom markup following the example: https://forge.autodesk.com/blog/implementing-custom-markups
The markup is created, highlighted and edited. We save and send information about the markup on the document to the server. When you open a document, the native markup is perfectly restored - edited, highlighted. But there is a problem with custom markup - they are displayed on the document, but they cannot be edited. They are not markups for viewer. It seems to me that this is due to the fact that viewer does not know about the type of custom markup (in the example this.type = 'smiley';)
How can this be fixed? Thanks!
We restore the markup in this way:
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)
})
It turned out to solve the problem by re-initializing the custom markup. currentMarkup.data is an SVG string that contains information about the custom markup. From this string, you need to pull the custom markup using a parser and load the markup without it. Then you need to re-create your custom markup.
After that, the custom markup will appear on the viewer and can be edited.
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)
})
}
}