Morphing Text
svelte-animations/morphing-textFreeBlock
A text component that smoothly morphs between multiple text strings with a blur transition effect.
Install it
npx shadcn@latest add https://sv-animations.vercel.app/r/morphing-text.jsonSource
1<script lang="ts">2 import { onMount, onDestroy } from "svelte";3 import { cn } from "$UTILS$";45 interface MorphingTextProps {6 texts: string[];7 class?: string;8 }910 let { texts, class: className }: MorphingTextProps = $props();1112 const morphTime = 1.5;13 const cooldownTime = 0.5;1415 let textIndex = $state(0);16 let morph = $state(0);17 let cooldown = $state(0);18 let time = $state(new Date());1920 let text1Ref: HTMLSpanElement | null = $state(null);21 let text2Ref: HTMLSpanElement | null = $state(null);2223 let animationFrameId: number | null = null;2425 const setStyles = (fraction: number) => {26 if (!text1Ref || !text2Ref) return;2728 text2Ref.style.filter = `blur(${Math.min(8 / fraction - 8, 100)}px)`;29 text2Ref.style.opacity = `${Math.pow(fraction, 0.4) * 100}%`;3031 const invertedFraction = 1 - fraction;32 text1Ref.style.filter = `blur(${Math.min(8 / invertedFraction - 8, 100)}px)`;33 text1Ref.style.opacity = `${Math.pow(invertedFraction, 0.4) * 100}%`;3435 text1Ref.textContent = texts[textIndex % texts.length];36 text2Ref.textContent = texts[(textIndex + 1) % texts.length];37 };3839 const doMorph = () => {40 morph -= cooldown;41 cooldown = 0;4243 let fraction = morph / morphTime;4445 if (fraction > 1) {46 cooldown = cooldownTime;47 fraction = 1;48 }4950 setStyles(fraction);5152 if (fraction === 1) {53 textIndex++;54 }55 };5657 const doCooldown = () => {58 morph = 0;59 if (text1Ref && text2Ref) {60 text2Ref.style.filter = "none";61 text2Ref.style.opacity = "100%";62 text1Ref.style.filter = "none";63 text1Ref.style.opacity = "0%";64 }65 };6667 const animate = () => {68 animationFrameId = requestAnimationFrame(animate);6970 const newTime = new Date();71 const dt = (newTime.getTime() - time.getTime()) / 1000;72 time = newTime;7374 cooldown -= dt;7576 if (cooldown <= 0) {77 doMorph();78 } else {79 doCooldown();80 }81 };8283 onMount(() => {84 animate();85 });8687 onDestroy(() => {88 if (animationFrameId !== null) {89 cancelAnimationFrame(animationFrameId);90 }91 });92</script>9394<div95 class={cn(96 "relative mx-auto h-16 w-full max-w-3xl text-center font-sans text-[40pt] leading-none font-bold filter-[url(#threshold)_blur(0.6px)] md:h-24 lg:text-[6rem]",97 className98 )}99>100 <span bind:this={text1Ref} class="absolute inset-x-0 top-0 m-auto inline-block w-full"></span>101 <span bind:this={text2Ref} class="absolute inset-x-0 top-0 m-auto inline-block w-full"></span>102103 <svg id="filters" class="fixed h-0 w-0" preserveAspectRatio="xMidYMid slice">104 <defs>105 <filter id="threshold">106// … 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 |
