Dot Wave
scrollxui/dot-waveFreeComponent
Dot-based waves ripple outward in symmetry, creating a subtle, motion-driven background layer
Live preview
live · rendered by the registry
Rendered by scrollxui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://scrollxui.dev/registry/dot-wave.jsonSource
1'use client';23import { useEffect, useRef } from 'react';4import { cn } from '@/lib/utils';56interface DotWaveProps {7 dotGap?: number;8 sphereRadius?: number;9 dotRadiusMax?: number;10 speed?: number;11 expansionSpeed?: number;12 repeatAnimation?: boolean;13 lightIntensity?: number;14 fadeIntensity?: number;15 followMouse?: boolean;16 className?: string;17 dotClassName?: string;18 children?: React.ReactNode;19 bgColor?: string;20 dotColor?: string;21}2223class Ease {24 value: number;25 begin: number;26 end: number;27 pow: number;28 maxDuration: number;29 time: number;30 duration: number;3132 constructor(value: number, pow: number, duration: number, timeBegin: number) {33 this.value = this.begin = this.end = value;34 this.pow = pow;35 this.maxDuration = duration;36 this.time = timeBegin;37 this.duration = 0;38 this.init();39 }4041 init() {42 this.begin = this.end;43 this.end = Math.random();44 this.time = 0;45 this.duration =46 Math.sqrt(Math.abs(this.end - this.begin)) * this.maxDuration;47 }4849 update(timeChange = 1) {50 let timeRatio = this.time / this.duration;5152 if (timeRatio < 0.5) {53 timeRatio = 0.5 * Math.pow(timeRatio * 2, this.pow);54 } else {55 timeRatio = 1 - 0.5 * Math.pow((1 - timeRatio) * 2, this.pow);56 }5758 this.value = this.begin + timeRatio * (this.end - this.begin);59 this.time += timeChange;60 if (this.time > this.duration) {61 this.init();62 }63 }64}6566export function DotWave({67 dotGap = 20,68 sphereRadius = 200,69 dotRadiusMax = 3,70 speed = 0.15,71 expansionSpeed = 150,72 repeatAnimation = true,73 lightIntensity = 0.5,74 fadeIntensity = 0.15,75 followMouse = false,76 className,77 dotClassName,78 children,79 bgColor = '#000000',80 dotColor = '#ffffff',81}: DotWaveProps) {82 const canvasRef = useRef<HTMLCanvasElement>(null);83 const containerRef = useRef<HTMLDivElement>(null);84 const stateRef = useRef({85 canvas: null as HTMLCanvasElement | null,86 ctx: null as CanvasRenderingContext2D | null,87 center: { x: 0, y: 0 },88 windowSize: { w: 0, h: 0 },89 circleNumber: { x: 0, y: 0 },90 posStart: { x: 0, y: 0 },91 easeX: new Ease(0.5, 2, 60, 0),92 easeY: new Ease(0.5, 2, 60, 0),93 animationId: 0,94 expansionRadius: 0,95 startTime: 0,96 bgColor: '#000000',97 dotColor: '#ffffff',98 });99100 useEffect(() => {101 const canvas = canvasRef.current;102 const container = containerRef.current;103 if (!canvas || !container) return;104105// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from scrollxui
All 180 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | scrollxui | Components | Free | 4 deps | |
| Alert Dialogalert-dialog | scrollxui | Components | Free | 7 deps | |
| Animated Buttonanimated-button | scrollxui | Components | Free | 4 deps | |
| Animated Tabsanimated-tabs | scrollxui | Components | Free | 1 dep | |
| Animated Testimonialsanimated-testimonials | scrollxui | Components | Free | 2 deps | |
| Animated TextGenerateanimated-textgenerate | scrollxui | Components | Free | 3 deps | |
| Announcementannouncement | scrollxui | Components | Free | 5 deps | |
| Aspect Ratioaspect-ratio | scrollxui | Components | Free | 1 dep |
