The SVG Overlay component allows you to add SVG elements over the DZI.
It excels at displaying large, flat, polygonal data.
The SVG Overlay element has no required props.
SVG elements are added to the DOM directly, rather than coming from an SVG image.
SVG Overlay is an intrinsic element, and doesn't need to be imported in order for you to use it.
Rather, the component is added as <svgOverlay />
.
const ViewerPage = () => {
const osdViewerRef = useRef<OSDViewerRef>(null)
return (
<>
<OSDViewer
ref={osdViewerRef}
>
<>
<viewport
zoom={1}
rotation={0}
/>
<tiledImage
tileUrlBase="http://localhost:4444/complex/00/"
url="http://localhost:4444/meta/anything-here"
/>
<svgOverlay />
</>
</OSDViewer>
</>
)
}
Interacting with SVG Overlay is done using useEffect
. Typically, your useEffect
would be given the dependency of the value that stores your data. In the simple examples below this wasn't necessary, but will be needed for any situation where data might need to change.
In order to add SVG elements, you will need to use document.createElementNS
You can learn more about how this method works on the MDN createElementNS page.
import { SVG_NAMESPACE } from '@lunit/osd-react-renderer'
export const useSVG = () => {
useEffect(() => {
const group = document.createElementNS(SVG_NAMESPACE, 'g')
group.setAttribute('id', 'my-svg-group')
group.setAttribute('fill', 'red')
group.setAttribute('opacity', '0.5')
const rect = document.createElementNS(SVG_NAMESPACE, 'rect')
rect.setAttribute('x','1000')
rect.setAttribute('y','1000')
rect.setAttribute('width','1000')
rect.setAttribute('height','1000')
group.appendChild(rect)
const svgRoot = document.getElementById(SVG_ROOT_ID)
if (svgRoot) {
svgRoot.appendChild(group)
} else {
console.error('SVG root not found')
}
}, [])
}
The OSD-R package provides an exported const for the SVG namespace value that is required when using this method.
It also provides an exported const for the SVG Overlay's root element ID.
Wrapping your individual SVG elements in a group <g>
and including an id attribute on your SVG group make setting element colour more efficient, as well as making it possible to manage visibility of groups of elements.
const ViewerPage = () => {
const osdViewerRef = useRef<OSDViewerRef>(null)
useSVG()
return (
<>
<OSDViewer
ref={osdViewerRef}
>
<>
<viewport
zoom={1}
rotation={0}
/>
<tiledImage
tileUrlBase="http://localhost:4444/complex/00/"
url="http://localhost:4444/meta/anything-here"
/>
<svgOverlay />
</>
</OSDViewer>
</>
)
}
SVG Overlay contains implicit logic for matching element position and scale to the viewer's pan and zoom, so the developer doesn't need to add anything to handle this.
It is also possible to control the visibility of SVG elements using state.
import { SVG_NAMESPACE } from '@lunit/osd-react-renderer'
export const useSVG = () => {
const [visible, setVisible] = useState(true)
useEffect(() => {
const group = document.createElementNS(SVG_NAMESPACE, 'g')
group.setAttribute('id', 'my-svg-group')
group.setAttribute('fill', 'red')
group.setAttribute('opacity', '0.5')
const rect = document.createElementNS(SVG_NAMESPACE, 'rect')
rect.setAttribute('x','1000')
rect.setAttribute('y','1000')
rect.setAttribute('width','1000')
rect.setAttribute('height','1000')
group.appendChild(rect)
const svgRoot = document.getElementById(SVG_ROOT_ID)
if (svgRoot) {
svgRoot.appendChild(group)
} else {
console.error('SVG root not found')
}
}, [])
useEffect(() => {
if (visible) {
document.getElementById('my-group-id')?.setAttribute('opacity', '0')
} else {
document.getElementById('my-group-id')?.setAttribute('opacity', '0.5')
}
}, [visible])
}
This is done using a separate useEffect
. Keeping this separate reduces the risk of re-initializing your SVG elements.