Skip to main content

Fonts and text

NiiVue draws its own text on the canvas: orientation labels, colorbar ticks, legends, measurements and the placeholder shown before an image loads. The text uses MSDF (multi-channel signed distance field) font atlases, which stay sharp at any size. Each font is a pair of files: a PNG atlas of the glyphs and a JSON file with their metrics.

Size and color​

Text settings are viewer properties:

  • fontScale sets the text size relative to the canvas (default 0.4).
  • fontMinSize is the smallest size in pixels (default 13), so labels stay readable on a small canvas.
  • fontColor is RGBA in the 0 to 1 range.
  • placeholderText is shown while the viewer has nothing loaded.
const nv = new NiiVue({ fontScale: 0.6, fontColor: [1, 1, 0, 1] })
nv.placeholderText = 'Drop an image here'

The text size is worked out when the view is laid out, so after changing fontScale or fontMinSize on a running viewer, call nv.resize() to apply it.

Other settings turn text elements on and off: isOrientationTextVisible for the orientation labels, isColorbarVisible, isLegendVisible and isMeasureUnitsVisible.

Changing the font​

The package bundles one font, Ubuntu (ASCII), and uses it by default. Other fonts load at runtime with setFontFromUrl, which takes the atlas and metrics URLs as named fields so the two cannot be swapped by mistake:

const base = 'https://raw.githubusercontent.com/niivue/fonts/main/fonts/'
await nv.setFontFromUrl({
atlas: `${base}Roboto-Regular.png`,
metrics: `${base}Roboto-Regular.json`,
})

The atlas becomes a GPU texture, so swapping the font rebuilds the view. If loading fails, NiiVue restores the previous font and rethrows the error. The server must send Access-Control-Allow-Origin for both files.

import NiiVue, { SLICE_TYPE } from '@niivue/niivue'

// Community MSDF fonts from github.com/niivue/fonts (served with CORS).
const FONTS = 'https://raw.githubusercontent.com/niivue/fonts/main/fonts/'

const demo = async (canvas, { ui, asset }) => {
const nv = new NiiVue({
sliceType: SLICE_TYPE.AXIAL,
isColorbarVisible: true,
fontColor: [1, 1, 1, 1],
})
await nv.attachToCanvas(canvas)
await nv.loadVolumes([{ url: asset('volumes/mni152.nii.gz') }])
const show = ui.status()
nv.addEventListener('locationChange', (e) => show(e.detail.string))

ui.select(
'Font',
['Ubuntu', 'UbuntuBold', 'Roboto-Regular', 'Garamond', 'GaramondBold'],
'Ubuntu',
async (name) => {
await nv.setFontFromUrl({
atlas: `${FONTS}${name}.png`,
metrics: `${FONTS}${name}.json`,
})
},
)
ui.slider(
'Size',
0.1,
1,
nv.fontScale,
(v) => {
nv.fontScale = v
nv.resize() // text size is computed when the view is laid out
},
0.05,
)
return nv
}

export default demo

The niivue/fonts repository holds community atlases, listed in its fonts/manifest.json. One of them, Poem, includes CJK glyphs; the Fonts example pairs it with Chinese placeholder text.

For a font you already have in memory (one you imported or fetched yourself) use setFont(font). The bundled font is exported, so you can switch back to it:

import { ubuntu } from '@niivue/niivue/assets/fonts'

await nv.setFont(ubuntu)

Making a font​

Build a new atlas with msdf-atlas-gen, listing the glyphs you need in a charset file:

msdf-atlas-gen -font NotoSansSC-Regular.ttf -charset charset.txt -pxrange 2 \
-dimensions 512 256 -format png -json Poem.json -imageout Poem.png

Host the PNG and JSON on a server with CORS and load them with setFontFromUrl. The fonts guide in the repository covers bundling a font into the package instead.