Country canvas
Frame one country and paint media inside its outline. A still, an animated GIF, a video, another canvas, or a live camera stream: clipped to the real boundary.
globe.focusOn("India", { isolate: true });
globe.setCountryMedia("India", "/launch-reel.mp4");
Focusing a country
globe.focusOn("India", { isolate: true, outlineWidth: 2 });
globe.clearFocus();
Or declaratively:
createGlobe(canvas, {
mode: "map",
focus: { country: "IN", isolate: true, dim: 0.16, outlineWidth: 2 },
});
| Field | Default | Meaning |
|---|---|---|
country | Not set | ISO code, numeric id or name |
isolate | false | Drop every other country entirely |
dim | 0.16 | Opacity of the others when not isolating. 1 leaves them alone |
outlineWidth | 1.6 | Stroke on the focused country |
padding | 0.82 | Fraction of the viewport to fill |
:::tip focusOn lifts the zoom ceiling
Framing India needs roughly 10.6× against a default maxZoom of 8, so focusOn raises the ceiling
to whatever the frame needs. clearFocus() puts it back.
:::
Size the canvas to the country or it will letterbox:
canvas.style.aspectRatio = String(1 / globe.countryAspect("India"));
globe.resize();
Adding media
createGlobe(canvas, {
countryMedia: {
IN: { src: "/reel.mp4", fit: "cover" },
BR: "/photo.jpg",
US: { src: "/loop.gif", opacity: 0.9 },
},
});
Keys match the same way choropleth keys do: ISO, numeric id or name.
| Field | Default | Meaning |
|---|---|---|
src | Not set | URL, image, video, canvas, ImageBitmap or MediaStream |
fit | "cover" | Mirrors CSS object-fit: cover, contain, fill |
type | auto | Force "image" or "video" when the URL has no useful extension |
opacity | 1 | |
blend | Not set | Any canvas composite operation, e.g. "screen" |
scale | 1 | Extra zoom on top of the fit |
offset | [0, 0] | Pixel nudge |
Source type is inferred from the extension: .mp4, .webm, .ogv, .mov become looping muted
video; .gif keeps animating; everything else loads as an image.
:::note Why GIFs need a DOM node
Browsers only advance an animated GIF that is attached to the document. CanvasGlobe parks the <img>
off-screen at 1×1 with near-zero opacity so drawImage sees live frames. Nothing is visible.
:::
Text cut out of a country
The same clip path, filled with type instead of pixels. The text auto-sizes to the shape's width.
globe.setCountryMedia("India", {
text: "MADE IN INDIA",
color: "#ffffff",
background: "#6d28d9",
});
| Field | Meaning |
|---|---|
text | The string |
color, background | Fill colours |
font, weight | Defaults to bold Inter |
size | Fixed px; omit to auto-fit |
fill | Fraction of the shape width to span. Default 0.86 |
opacity, offset |
Live streams
Because MediaStream is accepted directly, a webcam works:
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
globe.setCountryMedia("India", stream);
globe.focusOn("India", { isolate: true });
Exporting it
Combine with exporting to produce an asset:
// A transparent PNG of just the country, media and all
globe.exportImage({ preset: "square", transparent: true });
// Or a six-second clip
await globe.record({ duration: 6000, filename: "launch.webm" }).promise;
Cleaning up
setCountryMedia(country, null) releases one source; destroy() releases them all. Video elements
are paused and detached, so nothing keeps decoding in the background.