Skip to main content

Launch announcement video

"We just launched in India" reads very differently when the announcement video is playing inside the country.

Loading globe…

The code

import { createGlobe } from "canvas-globe";

const canvas = document.querySelector("#launch");

const globe = createGlobe(canvas, {
mode: "map",
theme: "atlas",
graticule: false,
stars: false,
autoRotate: false,
});

// Size the canvas to the country so it is not letterboxed.
canvas.style.aspectRatio = String(1 / globe.countryAspect("India"));
globe.resize();

globe.setCountryMedia("India", "/launch-reel.mp4");
globe.focusOn("India", { isolate: true, outlineWidth: 2, dim: 1 });

Or declaratively:

createGlobe(canvas, {
mode: "map",
focus: { country: "IN", isolate: true, outlineWidth: 2, dim: 1 },
countryMedia: { IN: { src: "/launch-reel.mp4", fit: "cover" } },
});

Exporting the asset

// A still for the post
globe.exportImage({ preset: "square" });

// A transparent PNG for slides
globe.exportImage({ preset: "square", transparent: true });

// A six-second clip for social
await globe.record({ duration: 6000, filename: "launch.webm" }).promise;

The clip is encoded in the tab by MediaRecorder: nothing uploads anywhere. Check the exported canRecord() helper first, since Safari's support is narrower than Chrome's.

Variations

Type instead of video. The same clip path filled with text:

globe.setCountryMedia("India", {
text: "MADE IN INDIA",
color: "#ffffff",
background: "#6d28d9",
});

Keep the neighbours. Drop isolate and dim them instead: this reads better for "our market" maps than a country floating in a void:

globe.focusOn("India", { isolate: false, dim: 0.18, outlineWidth: 2 });

Multiple countries at once. A montage of offices:

createGlobe(canvas, {
countryMedia: {
IN: "/offices/ahmedabad.jpg",
US: "/offices/austin.jpg",
DE: "/offices/berlin.jpg",
},
});

Live camera. MediaStream is accepted directly, which makes for a memorable conference demo:

const stream = await navigator.mediaDevices.getUserMedia({ video: true });
globe.setCountryMedia("India", stream);

Practical notes

  • Media is clipped to the real boundary: for India that is the full Survey of India outline, Andaman and Lakshadweep included.
  • Cross-origin video and images need permissive CORS headers, since frames are read via drawImage.
  • focusOn deliberately zooms past maxZoom; framing a country is an explicit request. clearFocus() restores the ceiling.
  • For a 9:16 story crop, export with { preset: "story" } rather than resizing the live canvas.