@automuxer/svelte-globe
v0.1.6
Published
The friendly, markup-first WebGL globe for Svelte, built on [COBE](https://cobe.vercel.app).
Readme
svelte-globe
The friendly, markup-first WebGL globe for Svelte, built on COBE.
Drop markers and arcs onto the globe as regular Svelte components, attach any DOM content to them as labels using CSS Anchor Positioning, and let Svelte transitions handle fade in/out as they rotate into and out of view.
Installation
npm install @automuxer/svelte-globeQuick start
<script>
import { fade } from "svelte/transition";
import {
Globe,
GlobeMarker,
GlobeMarkerLabel,
GlobeArc,
GlobeArcLabel,
buildTransition,
} from "@automuxer/svelte-globe";
</script>
<Globe size={400} sampleScale={1} brightness={7} spin={true}>
<GlobeMarker
lat={37.78}
long={-122.44}
size={0.04}
color="#3366ff"
transition={buildTransition(fade, { duration: 300 })}
>
<GlobeMarkerLabel>San Francisco</GlobeMarkerLabel>
</GlobeMarker>
<GlobeMarker
lat={51.51}
long={-0.13}
size={0.04}
color="#3366ff"
transition={buildTransition(fade, { duration: 300 })}
>
<GlobeMarkerLabel>London</GlobeMarkerLabel>
</GlobeMarker>
<GlobeArc
from={{ lat: 37.78, long: -122.44 }}
to={{ lat: 51.51, long: -0.13 }}
color="#4d80ff"
transition={buildTransition(fade, { duration: 300 })}
>
<GlobeArcLabel>SF → London</GlobeArcLabel>
</GlobeArc>
</Globe>Components
<Globe>
The root component COBE renders to.
size:numberWidth/height in pixels (square canvas). (required)sampleScale:numberfactor for sample density from 0—1 (required)brightness:numberLand brightness. (default:6)phi:numberInitial horizontal rotation (radians). (default:0)theta:numberInitial vertical rotation (radians). (default:0.2)dark:numberDark mode amount (0—1). (default:0)diffuse:numberDiffuse lighting amount. (default:1.2)baseColor:string(CSS color) Globe base color. (default:"#fff")glowColor:string(CSS color) Atmosphere glow color. (default:"#fff")oceanBrightness:numberBrightness of the ocean/base map. (default:0)spin:boolean | numberAuto-spin. Pass a number for a custom speed, defaults to -0.0002 when true. Use positive/negative numbers to set direction. (default:false)spinFollowsPan:booleanContinue spinning in the direction of the last pan/drag. (default:true)pan:boolean| number | {x:boolean|number,y:boolean|number} Whether to allow for user-panning. Set a number to control sensitivity, use an object to control per-axis. (default: { x: 600, y: 1500 })minTheta/maxTheta:numberClamp vertical rotation. (default:±Infinity)children:Snippet<GlobeMarker>/<GlobeArc>elements. (optional)
<GlobeMarker>
Declares a marker and (optionally) renders DOM content anchored to it.
lat:numberLatitude. (required)long:numberLongitude. (required)size:numberMarker dot size. (default:0.035)color:string(CSS color) Marker dot color. (default:"#3366ff")id:stringStable key used for the--cobe-{id}CSS anchor. Pass your own if you need a deterministic id (e.g. to key off external data). (default: random UUID)visible:boolean(bindable)truewhen the marker is facing the camera. See Binding position and visibility. (optional)position:{ x: number; y: number }(bindable) Normalized[0, 1]screen position of the marker. See Binding position and visibility. (optional)transition:BuiltTransitionWrap a Svelte transition withbuildTransitionand pass it here to animate the label in/out. (optional)children:SnippetContent rendered anchored above the marker (use<GlobeMarkerLabel>or your own markup). Omit to render just the dot, no label. (optional)
Any other props (class, style, onclick, etc.) are spread onto the
anchored wrapper <div>.
<GlobeArc>
Same idea as <GlobeMarker>, anchored to the arc's midpoint instead.
from:{ lat: number; long: number }Start{ lat: latitude, long: longitude }. (required)to:{ lat: number; long: number }End{ lat: latitude, long: longitude }. (required)color:string(CSS color) Arc color. (default:"#3366ff")id:stringStable key used for the--cobe-arc-{id}CSS anchor. (default: random UUID)visible:boolean(bindable)truewhen the arc's midpoint is facing the camera. See Binding position and visibility. (optional)position:{ x: number; y: number }(bindable) Normalized[0, 1]screen position of the arc's midpoint. See Binding position and visibility. (optional)transition:BuiltTransitionSeebuildTransition. (optional)children:SnippetContent rendered anchored above the arc's peak. (optional)
<GlobeMarkerLabel> / <GlobeArcLabel>
Minimal pre-styled label chips are available using GlobeMarkerLabel or GlobeArcLabel.
Pass any other
markup as <GlobeMarker>/<GlobeArc> children instead if you want full
control over the label's appearance:
<GlobeMarker lat={37.78} long={-122.44}>
<div class="my-own-label">San Francisco</div>
</GlobeMarker>Binding position and visibility
<GlobeMarker>/<GlobeArc> children are positioned via CSS Anchor
Positioning, and are mounted/disposed each time the point comes into or out of view.
If you need the raw data instead (e.g. to render an overlay that isn't a
direct child), bind
visible and position directly:
<script>
let visible = $state(false);
let position = $state();
</script>
<GlobeMarker lat={37.78} long={-122.44} bind:visible bind:position />
{#if visible && position}
<div
style:position="absolute"
style:left="{position.x * 100}%"
style:top="{position.y * 100}%"
>
San Francisco
</div>
{/if}position is { x, y }, normalized to [0, 1] relative to the <Globe>'s
wrapper element. visible is true when the marker/arc is currently facing
the camera. Both update on every frame as the
globe rotates.
Transitions
Svelte doesn't natively support the transition: directive being passed to components, so we use a custom transition prop.
Use buildTransition to wrap a transition function (and its params) into something you can hand to the transition
prop on <GlobeMarker>/<GlobeArc>:
<script>
import { fade } from "svelte/transition";
import { buildTransition } from "@automuxer/svelte-globe";
</script>
<GlobeMarker
lat={37.78}
long={-122.44}
transition={buildTransition(fade, { duration: 300 })}
>
...
</GlobeMarker>License
svelte-globe: The friendly, markup-first WebGL globe for Svelte.
Copyright (C) 2026 Software Freedom Conservancy
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along with this program. If not, see https://www.gnu.org/licenses/.
