DVD Screensaver
refinery/dvd-screensaverFreeComponent
Bouncing logo screensaver with color shifts on bounce.
Live preview
live · rendered by the registry
Rendered by refinery on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://refinery.abhii.me/r/dvd-screensaver.jsonSource
1"use client";23import { motion, useAnimationFrame } from "motion/react";4import { useRef, useState } from "react";5import { cn } from "@/lib/utils";67const COLORS = [8 "#FF4444",9 "#44AAFF",10 "#44FF88",11 "#FFCC44",12 "#CC44FF",13 "#FF8844",14 "#44FFEE",15];1617interface DVDScreensaverProps {18 text?: string;19 subText?: string;20 speed?: number;21 className?: string;22}2324export default function DVDScreensaver({25 text = "Refinery",26 subText = "UI Vault",27 speed = 2,28 className = "",29}: DVDScreensaverProps) {30 const containerRef = useRef<HTMLDivElement>(null);31 const logoRef = useRef<HTMLDivElement>(null);3233 const pos = useRef({ x: 80, y: 80 });34 const vel = useRef({ vx: speed, vy: speed });35 const colorIdxRef = useRef(0);3637 const [color, setColor] = useState(COLORS[0]);38 const [bounces, setBounces] = useState(0);39 const [corners, setCorners] = useState(0);40 const [cornerFlashKey, setCornerFlashKey] = useState(0);4142 useAnimationFrame(() => {43 const container = containerRef.current;44 const logo = logoRef.current;45 if (!container || !logo) return;4647 const cW = container.clientWidth;48 const cH = container.clientHeight;49 const lW = logo.offsetWidth;50 const lH = logo.offsetHeight;5152 pos.current.x += vel.current.vx;53 pos.current.y += vel.current.vy;5455 let hitX = false;56 let hitY = false;5758 if (pos.current.x <= 0) {59 pos.current.x = 0;60 vel.current.vx = Math.abs(vel.current.vx);61 hitX = true;62 } else if (pos.current.x + lW >= cW) {63 pos.current.x = cW - lW;64 vel.current.vx = -Math.abs(vel.current.vx);65 hitX = true;66 }6768 if (pos.current.y <= 0) {69 pos.current.y = 0;70 vel.current.vy = Math.abs(vel.current.vy);71 hitY = true;72 } else if (pos.current.y + lH >= cH) {73 pos.current.y = cH - lH;74 vel.current.vy = -Math.abs(vel.current.vy);75 hitY = true;76 }7778 if (hitX || hitY) {79 if (hitX) vel.current.vx += (Math.random() - 0.5) * 0.4;80 if (hitY) vel.current.vy += (Math.random() - 0.5) * 0.4;8182 const mag = Math.sqrt(vel.current.vx ** 2 + vel.current.vy ** 2);83 vel.current.vx = (vel.current.vx / mag) * speed;84 vel.current.vy = (vel.current.vy / mag) * speed;8586 colorIdxRef.current = (colorIdxRef.current + 1) % COLORS.length;87 setColor(COLORS[colorIdxRef.current]);88 setBounces((b) => b + 1);8990 if (hitX && hitY) {91 setCorners((c) => c + 1);92 setCornerFlashKey((k) => k + 1);93 }94 }9596// … truncated
What it pulls in
npm packages
Files it writes
More from refinery
All 16 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Analog Clock Screensaveranalog-clock-screensaver | refinery | Components | Free | 1 dep | |
| Avatar Circleavatar-circle | refinery | Components | Free | 1 dep | |
| Floating Cardfloating-card | refinery | Components | Free | 1 dep | |
| Floating Navfloating-nav | refinery | Components | Free | 1 dep | |
| Glowy Buttonglowy-button | refinery | Components | Free | 1 dep | |
| Move To Topmove-to-top-button | refinery | Components | Free | 1 dep | |
| Notification Badgenotification-badge | refinery | Components | Free | 1 dep | |
| Sleeping Cat Screensaversleeping-cat-screensaver | refinery | Components | Free | 2 deps |
