tiny-label
v2.0.1
Published
SDF based labels for the mixmap ecosystem. A layer around [`tiny-atlas`](https://www.npmjs.com/package/tiny-atlas) and [`label-placement-engine`](https://www.npmjs.com/package/label-placement-engine), intended to work well with [`mixmap`][] & [`mixmap-geo
Readme
tiny-label
SDF based labels for the mixmap ecosystem. A layer around tiny-atlas and label-placement-engine, intended to work well with [mixmap][] & [mixmap-georender].
Motivated by the fact that I can't seem to get legible output from mixmap-georender/text which is based on qbzf and label-placement-engine.
usage
This is a complete map example, which roughly breaks down to the following:
import { Label, Shaders: LabelShaders } from 'tiny-label'
import createRegl from 'regl'
import mixmap from '@rubenrodriguez/mixmap'
import prepare, { propsForMap } from '@rubenrodriguez/mixmap-georender/prepare'
import { createGlyphProps } from '@rubenrodriguez/mixmap-georender/text'
import makeTex = '@rubenrodriguez/georender-style2png/promise'
const mix = mixmap(createRegl, {
extensions: ['oes_element_index_uint'],
})
const map = mix.create({
viewbox: [-67.356661,17.854597,-65.575714,18.517377],
backgroundColor: [0.5, 0.5, 0.5, 1.0],
})
// stylesheet as as input to `georender-style2png`
// [georender-style2png](https://github.com/rubillionaire/georender-style2png)
// can be computed in the browser [1], or pre saved as png + decoded in browser [2]
// 1. https://github.com/rubillionaire/pr-sketch/blob/main/tiny-label-03/index.js
// 2. https://github.com/rubillionaire/pr-sketch/blob/main/basic-stack-01/index.js
const stylesheet = {
}
makeTexture(stylesheet)
.then((style) = >{
const labelShaders = LabelShaders(map)
const draw = {
label: fontFamily.map(() => map.createDraw(labelShaders.label)),
}
const stylePixels = {
data: style.data,
width: style.width,
height: style.height,
}
// fetch or create decoded georender gpu ready data
// - [georender-geojson](https://github.com/rubillionaire/georender-geojson)
// - [georender-pack](https://github.com/rubillionaire/georender-pack)
const decoded = decodeGeorender()
const geodata = prepare({
stylePixels,
imageSize: [style.width, style.height],
decoded,
zoomStart: 1,
zoomEnd: 21,
})
const props = geodata.update(propsForMap(map))
// Also can be initialized in a web worker
const label = new Label({
fontFamily: style.labelFontFamily,
style,
})
// label placement can be done in a web worker
const labelProps = label.update(props, propsForMap(map))
// creating glyphs props requires access to the main thread's webgl
// context, so must be done on the main thread
createGlyphProps(labelProps, map)
// call the draw commands for each group of labels and their glyphs
for (let i = 0; i < fontFamily.length; i++) {
draw.label[i].props = labelProps.glyphs[i]
}
map.draw()
})The labeling can also be done in a worker, the package exports a LabelPropsWorker which is a function that returns the Web Worker.
import { LabelPropsWorker } from 'tiny-label'
import { propsForMap } from '@rubenrodriguez/mixmap-georender/prepare'
const worker = LabelPropsWorker()
worker.postMessage({
type: 'initialize',
options: { fontFamily: ['Arial'] },
})
worker.addEventListener('message', (msg) => {
if (msg.type !== 'update') return
const { labelProps } = msg.detail
})
worker.postMessage({
type: 'update',
options: [
decodedGeorender, // decoded georender compatible
propsForMap(map),
],
})