Icon Cloud
svelte-animations/icon-cloudFreeBlock
An interactive 3D tag cloud component that displays icons or images in a sphere formation with smooth rotation and drag interactions.
Install it
npx shadcn@latest add https://sv-animations.vercel.app/r/icon-cloud.jsonSource
1<script lang="ts">2 import { onMount } from "svelte";3 import type { Component } from "svelte";45 interface Icon {6 x: number;7 y: number;8 z: number;9 scale: number;10 opacity: number;11 id: number;12 }1314 interface IconCloudProps {15 icons?: Component[];16 images?: string[];17 class?: string;18 }1920 let { icons, images, class: className = "" }: IconCloudProps = $props();2122 let canvasRef: HTMLCanvasElement | null = $state(null);23 let iconPositions = $state<Icon[]>([]);24 let isDragging = $state(false);25 let lastMousePos = $state({ x: 0, y: 0 });26 let mousePos = $state({ x: 0, y: 0 });27 let targetRotation = $state<{28 x: number;29 y: number;30 startX: number;31 startY: number;32 distance: number;33 startTime: number;34 duration: number;35 } | null>(null);3637 let animationFrameId = 0;38 let rotationRef = { x: 0, y: 0 };39 let iconCanvases: HTMLCanvasElement[] = [];40 let imagesLoaded: boolean[] = [];4142 function easeOutCubic(t: number): number {43 return 1 - Math.pow(1 - t, 3);44 }4546 // Create icon canvases47 $effect(() => {48 if (!icons && !images) return;4950 const items = icons || images || [];51 imagesLoaded = new Array(items.length).fill(false);5253 const newIconCanvases = items.map((_item, index) => {54 const offscreen = document.createElement("canvas");55 offscreen.width = 40;56 offscreen.height = 40;57 const offCtx = offscreen.getContext("2d");5859 if (offCtx) {60 if (images) {61 const img = new Image();62 img.crossOrigin = "anonymous";63 img.src = items[index] as string;64 img.onload = () => {65 offCtx.clearRect(0, 0, offscreen.width, offscreen.height);66 offCtx.beginPath();67 offCtx.arc(20, 20, 20, 0, Math.PI * 2);68 offCtx.closePath();69 offCtx.clip();70 offCtx.drawImage(img, 0, 0, 40, 40);71 imagesLoaded[index] = true;72 };73 }74 }75 return offscreen;76 });7778 iconCanvases = newIconCanvases;79 });8081 // Generate initial icon positions on a sphere82 $effect(() => {83 const items = icons || images || [];84 const newIcons: Icon[] = [];85 const numIcons = items.length || 20;8687 const offset = 2 / numIcons;88 const increment = Math.PI * (3 - Math.sqrt(5));8990 for (let i = 0; i < numIcons; i++) {91 const y = i * offset - 1 + offset / 2;92 const r = Math.sqrt(1 - y * y);93 const phi = i * increment;9495 const x = Math.cos(phi) * r;96 const z = Math.sin(phi) * r;9798 newIcons.push({99 x: x * 100,100 y: y * 100,101 z: z * 100,102 scale: 1,103 opacity: 1,104 id: i,105 });106 }107 iconPositions = newIcons;108// … truncated
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 |
