Skip to content

labels

HTML label overlay. LabelLayer keeps geometry on the GPU and renders only the visible labels into the DOM, positioning anchors (reference-space) under a core!ViewTransform; cullLabels does the viewport + collision culling.

import { LabelLayer } from "@mapequation/d3gl/labels";
const labels = new LabelLayer(containerEl, (a) => a.text);
labels.update(anchors, transform, { width, height });
ClassDescription
LabelLayerAn HTML overlay of absolutely-positioned label elements. On each update it maps reference anchors through the view transform to screen pixels, culls to the viewport with collision resolution, and reconciles the DOM (reusing nodes by id). Geometry stays on the GPU; only the surviving labels are in the DOM.
InterfaceDescription
CullOptions-
LabelAnchorA label anchored in REFERENCE (projected, pre-transform) pixel space.
LabelBoxA label positioned in SCREEN pixels (after the view transform is applied).
LabelGeometryThe realised screen geometry of a label: its four corners, their AABB, whether it is axis-aligned (fast-path collision), and the CSS transform that reproduces the box.
Type AliasDescription
TextAnchorWhere the anchor point sits along the label’s own text axis — like SVG text-anchor.
FunctionDescription
cullLabelsReduce label candidates to a renderable subset: drop anchors outside the viewport (+padding), then greedily place highest-priority first, skipping any that collide with an already-placed box. Collision uses each label’s true oriented footprint (see labelGeometry), so rotated labels pack by the space they actually occupy on screen rather than their un-rotated dimensions. This keeps the DOM at a few hundred nodes regardless of how many features exist (the “geometry on GPU, only visible labels in DOM” approach).
labelGeometryResolve a LabelBox to its on-screen geometry. Plain labels (no rotation) keep the historical top-left box and own their CSS transform. Oriented labels (rotation set) place the text along the rotated axis, vertically centred on the anchor, with text-anchor and the optional upright flip folded in — and emit the matching CSS transform. The collision corners and the transform come from the same computation, so render and culling stay consistent.