Skip to main content

Linking viewers

Several viewers on one page can follow each other: move the crosshair, zoom or rotate in one, and the others match. Click, scroll or rotate in either viewer below.

import NiiVue from '@niivue/niivue'

const demo = async (canvas, { ui, asset, canvases }) => {
const nv1 = new NiiVue()
const nv2 = new NiiVue()
await nv1.attachToCanvas(canvas)
await nv2.attachToCanvas(canvases[1])
await nv1.loadVolumes([{ url: asset('volumes/mni152.nii.gz') }])
await nv2.loadVolumes([
{ url: asset('volumes/mni152.nii.gz'), colormap: 'hot' },
])

const link = (mode: string): void => {
nv1.broadcastTo(mode === 'Independent' ? undefined : [nv2])
nv2.broadcastTo(mode === 'Both ways' ? [nv1] : undefined)
}
link('Both ways')
ui.select(
'Link',
['Both ways', 'Left drives right', 'Independent'],
'Both ways',
link,
)
return [nv1, nv2]
}

export default demo

broadcastTo​

nv1.broadcastTo(targets) makes nv1 push its view to one viewer or a list of viewers whenever it redraws. The link is one-way, so for two viewers that drive each other, link both:

nv1.broadcastTo([nv2])
nv2.broadcastTo([nv1])

Each call replaces the viewer's previous targets. Call broadcastTo() with no arguments to stop broadcasting.

What is synced​

The optional second argument says what to send. It is a SyncOpts object, and it replaces the default rather than adding to it:

KeyWhat it copies
'2d'the crosshair position and the 2D pan and zoom
'3d'the render's azimuth, elevation and zoom (scaleMultiplier)
clipPlaneall clip planes
crosshairthe crosshair position only
sliceTypethe slice type
calMin, calMaxthe display range of volume 0
viewportthe canvas-level pan and zoom, between viewers on different canvases

The default is { '2d': true, '3d': true, clipPlane: true }. To also match the slice type, and only that besides the crosshair:

nv1.broadcastTo([nv2], { crosshair: true, sliceType: true })

The crosshair is passed in millimeters, not voxels, so viewers with different images stay on the same anatomical point as long as the images share a space (for example, a T1 and a statistical map both in MNI space). Everything else, such as the loaded volumes, colormaps and layout, stays independent. In the demo the right viewer uses a different colormap.

Viewers on one canvas​

Linked viewers do not need their own canvases. Give each one a region of a shared canvas with bounds (see Several viewers in one canvas) and link them the same way.

See also​

  • Synchronize: two linked viewers with one-way and two-way options.
  • Bounds: two linked viewers sharing one canvas.