Globe
svelte-animations/globeFreeBlock
An autorotating, interactive, and highly performant globe made using WebGL.
Install it
npx shadcn@latest add https://sv-animations.vercel.app/r/globe.jsonSource
1<script lang="ts">2 import type { COBEOptions, Globe } from "cobe";3 import { Spring } from "svelte/motion";4 import { onDestroy, onMount } from "svelte";5 import { cn } from "$UTILS$";67 interface Props {8 class?: string;9 config?: Partial<COBEOptions>;10 }1112 let { class: className, config = {} }: Props = $props();1314 let size = $derived(config.width ?? 300);1516 const baseTheta = 0.2;17 const thetaOffsetMin = -0.4;18 const thetaOffsetMax = 0.4;1920 let canvas: HTMLCanvasElement | null = null;21 let globe: Globe | null = null;22 let observer: IntersectionObserver | null = null;23 let createGlobePromise: Promise<typeof import("cobe").default> | null = null;24 let isVisible = false;25 let isDragging = $state(false);2627 let frame = 0;28 let autoPhi = 0;29 let dragStart: { x: number; y: number; phi: number; theta: number } | null = null;30 let lastPointer: { x: number; y: number; t: number } | null = null;31 let releaseVelocity = { phi: 0, theta: 0 };3233 const initialPhi = $derived(config.phi ?? 0);34 const initialTheta = $derived(config.theta ?? baseTheta);3536 const phiOffset = new Spring(0, {37 stiffness: 0.12,38 damping: 0.7,39 precision: 0.0001,40 });4142 const thetaOffset = new Spring(0, {43 stiffness: 0.12,44 damping: 0.7,45 precision: 0.0001,46 });4748 function clamp(value: number, min: number, max: number) {49 return Math.min(max, Math.max(min, value));50 }5152 function handlePointerDown(event: PointerEvent) {53 dragStart = {54 x: event.clientX,55 y: event.clientY,56 phi: phiOffset.target,57 theta: thetaOffset.target,58 };59 lastPointer = { x: event.clientX, y: event.clientY, t: performance.now() };60 releaseVelocity = { phi: 0, theta: 0 };61 isDragging = true;62 canvas?.setPointerCapture?.(event.pointerId);63 }6465 function handlePointerMove(event: PointerEvent) {66 if (!dragStart) return;6768 const nextPhi = dragStart.phi + (event.clientX - dragStart.x) / 300;69 const nextTheta = clamp(70 dragStart.theta + (event.clientY - dragStart.y) / 1000,71 thetaOffsetMin,72 thetaOffsetMax73 );7475 void phiOffset.set(nextPhi, { instant: true });76 void thetaOffset.set(nextTheta, { instant: true });7778 const now = performance.now();79 if (lastPointer) {80 const dt = Math.max(now - lastPointer.t, 1);81 const maxVelocity = 0.15;8283 releaseVelocity = {84 phi: clamp(((event.clientX - lastPointer.x) / dt) * 0.3, -maxVelocity, maxVelocity),85 theta: clamp(86 ((event.clientY - lastPointer.y) / dt) * 0.08,87 -maxVelocity,88 maxVelocity89 ),90 };91 }9293// … truncated
What it pulls in
npm packages
Files it writes
More from Svelte Animations
All 66 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Animated Beamanimated-beam | Svelte Animations | Blocks | Free | 1 dep · 6 files | |
| Animated Circular Progress Baranimated-circular-progress-bar | Svelte Animations | Blocks | Free | no deps · 2 files | |
| Animated Gradient Textanimated-gradient-text | Svelte Animations | Blocks | Free | no deps · 2 files | |
| Animated Grid Patternanimated-grid-pattern | Svelte Animations | Blocks | Free | 1 dep · 2 files | |
| Animated Listanimated-list | Svelte Animations | Blocks | Free | 1 dep · 2 files | |
| Animated Shiny Textanimated-shiny-text | Svelte Animations | Blocks | Free | no deps | |
| Animated Theme Toggleranimated-theme-toggler | Svelte Animations | Blocks | Free | no deps · 2 files | |
| Arc Timelinearc-timeline | Svelte Animations | Blocks | Free | no deps · 3 files |
