Skip to main content

Overlays

Layers that sit on top of the base map. All of them compose.

Heatmap

Additive density blobs can replace individual markers or sit underneath them.

createGlobe(canvas, {
heatmap: { radius: 30, intensity: 0.5, color: "#f97316" },
markers,
});
Loading globe…
FieldDefault
radius30: blob radius in px at full weight
intensity0.5: peak opacity
colortheme marker

Spikes

Bars standing off the surface, scaled by count. Markers ride the tip, so the bar is never buried.

createGlobe(canvas, { spikes: { height: 0.28, width: 2.4 }, markers });

height is the tallest spike as a fraction of the globe radius.

Labels

Text with collision avoidance: the highest-weight label wins and overlapping ones are dropped rather than allowed to pile up.

labels: "markers"; // marker.label / .name / .city
labels: "countries"; // country names, sized to the shape
labels: "both";
Loading globe…

Legend

// Continuous ramp
legend: { title: "Visits", scale: { domain: [0, 1000], range: ["#e0f2fe", "#0369a1"] } }

// Discrete swatches
legend: { title: "Tier", items: [{ color: "#0369a1", label: "Enterprise" }] }

position accepts "top-left", "top-right", "bottom-left" (default) or "bottom-right".

Counter

A rolling headline number. It eases whenever the value changes, which makes a live figure feel alive.

createGlobe(canvas, {
counter: {
value: 21947,
label: "customers worldwide",
format: (n) => `$${Math.round(n).toLocaleString()}`,
position: "top-left",
},
});
Loading globe…

Title

Headline text is painted onto the canvas. exportImage() therefore returns a complete graphic without requiring a separate HTML overlay.

createGlobe(canvas, {
title: {
text: "Trusted in 68 countries",
subtitle: "21,947 teams and counting",
position: "top-center",
},
});
FieldDefault
textrequired
subtitleNot set
size6.2% of the smaller canvas side
subtitleSize42% of size
weight800
fontInter,system-ui,sans-serif
color / subtitleColortheme label
position"top-left": also top-center, top-right, bottom-*
padding22
Loading globe…

Watermark

A logo, a wordmark, or both. Anything you can draw works as image: a URL, an <img>, a <canvas> or an ImageBitmap.

createGlobe(canvas, {
watermark: {
image: "/logo.svg",
text: "acme.com",
height: 32,
opacity: 0.85,
position: "bottom-right",
},
});

Because it is part of the render, every exportImage(), exportBlob() and record() frame carries it. That is the difference between a screenshot someone can crop your brand out of and an asset that stays attributed wherever it gets reposted.

Loading globe…

Callouts

Leader lines with a label: for explainer graphics where a tooltip will not do.

annotations: [
{ lat: 23.03, lon: 72.58, text: "HQ: Ahmedabad" },
{ lat: 51.5, lon: -0.12, text: "EU office", dx: -70, dy: -40 },
];

dx/dy offset the label from the point; negative dx flips the box to the left.

Timeline

Hide markers whose date has not arrived yet, then animate the range.

const markers = [
{ lat: 23.03, lon: 72.58, date: "2024-01-15" },
{ lat: 51.5, lon: -0.12, date: "2024-06-02" },
];

globe.setTimelineAt("2024-03-01"); // static cut-off
globe.playTimeline({ duration: 6000, loop: true }); // animate the whole range
globe.stopTimeline();

With no from/to, playTimeline derives the range from your markers' dates. Markers with no date always show.

Loading globe…