Skip to content

Latest commit

 

History

History
181 lines (127 loc) · 4.72 KB

SVGOverlay.md

File metadata and controls

181 lines (127 loc) · 4.72 KB

Documentation for SVG Overlay

Summary

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.

Basic Usage

Adding SVG Overlay to your OSD-R Viewport

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>
    </>
  )
}
  

Adding SVG elements

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.

Conditionally Rendering with SVG

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.

Further Reading