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

Hex bins​

Hex bins turn a dense marker set into readable, interactive density cells. They work in both globe and flat-map modes and recompute after rotation, pan, or zoom because aggregation happens after projection.

createGlobe(canvas, {
markers,
hexBins: {
radius: 18,
value: "sum",
colorRange: ["#dbeafe", "#38bdf8", "#1d4ed8"],
padding: 1.4,
showCount: true,
},
tooltip: (target, kind) => kind === "hex-bin"
? `${target.markerCount} locations, ${target.value} requests`
: target.label,
});

Clicking or hovering a cell returns its source markers in target.markers. Use value: "count" to colour by marker count instead of summed marker values, and set hideMarkers: false to keep individual markers above the grid.

FieldDefault
radius18: cell radius in screen pixels
minValue1
value"sum"; also "count"
colorRangeA ramp derived from the theme marker colour
opacity0.82
strokeWidth0.8
padding1.5
showCountfalse
hideMarkerstrue

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…

Talk to a real person

Live human support. Choose what you need help with.