Hi all. I’m Alejandro, a product designer who codes. I kept needing dotted world maps and spinning globes for landing pages and decks, so I built a studio for them with React and Three.js. You pick the world, a continent, a country or a US state, choose one of 21 looks, adjust the dots, colors and density, and export a PNG, SVG, WebM, MP4, GIF or an embed. You can also paste lat,lng,value lines to plot your own data as markers, joined by arcs on the globe. It’s MIT licensed and needs no signup.
Live: Globestudio: Open-Source Dotted Maps and 3D Globes
Source: GitHub - alevizio/globestudio: Open-source dotted maps and animated 3D globes for designers. 21 looks, PNG, SVG, WebM, MP4 and GIF export, embeds, a React component, a Figma plugin and an MCP server. MIT. · GitHub
A few notes on how it works:
-
Most dots come from the dotted-map package (US states use my own Albers USA grid). They render as InstancedMeshes, one per layer: normally one for the whole field and one for the dots you click, plus glow or RGB split copies on the looks that use them. Switching between the flat map and the globe moves each dot along a flat, cylinder, sphere path. Each frame re-bakes a third of the instance matrices on the CPU and uploads just that range through updateRanges, so the morph never rebuilds a mesh.
-
A look is a preset (dot shape, colors, density, globe settings) plus at most one of 24 effects, including halftone, risograph, Bayer and an Atkinson style dither, CRT and aurora. All 24 are branches of one fragment shader in a single ShaderPass, and a float uniform picks the branch, so the composer is built once, when the canvas mounts. Bloom also enables an UnrealBloomPass that otherwise sits in the chain switched off. The shader ends by compositing a separately rendered background target behind the effect, which is how halftone and the other pattern effects mark only the globe while the starfield shows through the gaps.
-
Hi-res PNG export (up to 4x) renders the composer once more at the export pixel ratio and reads the canvas back with toBlob.
-
While you interact, the render loop averages the frame rate over 60 frames and steps the pixel ratio down by 0.25 (never below 1) under 50 fps, then back up above 58 fps. Idle frames are capped at about 30 fps, and the loop leaves them out of that average so it doesn’t mistake the cap for a slow GPU.
What isn’t great yet: heavy looks at max density drop frames on weaker GPUs. If it stutters for you, I’d like to know your GPU and browser.
