diff --git a/src/components/common/PreviewText.vue b/src/components/common/PreviewText.vue new file mode 100644 index 0000000..f62cdf4 --- /dev/null +++ b/src/components/common/PreviewText.vue @@ -0,0 +1,33 @@ + + + + + diff --git a/src/constants/Categories.ts b/src/constants/Categories.ts index 1fe5c08..aa641b0 100644 --- a/src/constants/Categories.ts +++ b/src/constants/Categories.ts @@ -22,7 +22,8 @@ export const CATEGORIES = [ 'True Focus', 'Scroll Float', 'Scroll Reveal', - 'Rotating Text' + 'Rotating Text', + 'Glitch Text' ] }, { diff --git a/src/constants/Components.ts b/src/constants/Components.ts index ab2deab..b911a4f 100644 --- a/src/constants/Components.ts +++ b/src/constants/Components.ts @@ -27,7 +27,8 @@ const textAnimations = { 'true-focus': () => import("../demo/TextAnimations/TrueFocusDemo.vue"), 'scroll-float': () => import("../demo/TextAnimations/ScrollFloatDemo.vue"), 'scroll-reveal': ()=> import("../demo/TextAnimations/ScrollRevealDemo.vue"), - 'rotating-text': ()=> import("../demo/TextAnimations/RotatingTextDemo.vue") + 'rotating-text': ()=> import("../demo/TextAnimations/RotatingTextDemo.vue"), + 'glitch-text': () => import("../demo/TextAnimations/GlitchTextDemo.vue"), }; const components = { diff --git a/src/constants/code/TextAnimations/glitchTextCode.ts b/src/constants/code/TextAnimations/glitchTextCode.ts new file mode 100644 index 0000000..0c92253 --- /dev/null +++ b/src/constants/code/TextAnimations/glitchTextCode.ts @@ -0,0 +1,19 @@ +import code from '@/content/TextAnimations/GlitchText/GlitchText.vue?raw'; +import type { CodeObject } from '../../../types/code'; + +export const glitchText: CodeObject = { + cli: `npx jsrepo add https://vue-bits.dev/ui/TextAnimations/GlitchText`, + usage: ` + +`, + code +}; diff --git a/src/content/TextAnimations/GlitchText/GlitchText.css b/src/content/TextAnimations/GlitchText/GlitchText.css new file mode 100644 index 0000000..faff805 --- /dev/null +++ b/src/content/TextAnimations/GlitchText/GlitchText.css @@ -0,0 +1,120 @@ +.glitch { + color: #fff; + font-size: clamp(2rem, 10vw, 8rem); + white-space: nowrap; + font-weight: 900; + position: relative; + margin: 0 auto; + user-select: none; + cursor: pointer; +} + +.glitch::after, +.glitch::before { + content: attr(data-text); + position: absolute; + top: 0; + color: #fff; + background-color: #060010; + overflow: hidden; + clip-path: inset(0 0 0 0); +} + +.glitch:not(.enable-on-hover)::after { + left: 10px; + text-shadow: var(--after-shadow, -10px 0 red); + animation: animate-glitch var(--after-duration, 3s) infinite linear alternate-reverse; +} +.glitch:not(.enable-on-hover)::before { + left: -10px; + text-shadow: var(--before-shadow, 10px 0 cyan); + animation: animate-glitch var(--before-duration, 2s) infinite linear alternate-reverse; +} + +.glitch.enable-on-hover::after, +.glitch.enable-on-hover::before { + content: ''; + opacity: 0; + animation: none; +} + +.glitch.enable-on-hover:hover::after { + content: attr(data-text); + opacity: 1; + left: 10px; + text-shadow: var(--after-shadow, -10px 0 red); + animation: animate-glitch var(--after-duration, 3s) infinite linear alternate-reverse; +} +.glitch.enable-on-hover:hover::before { + content: attr(data-text); + opacity: 1; + left: -10px; + text-shadow: var(--before-shadow, 10px 0 cyan); + animation: animate-glitch var(--before-duration, 2s) infinite linear alternate-reverse; +} + +@keyframes animate-glitch { + 0% { + clip-path: inset(20% 0 50% 0); + } + 5% { + clip-path: inset(10% 0 60% 0); + } + 10% { + clip-path: inset(15% 0 55% 0); + } + 15% { + clip-path: inset(25% 0 35% 0); + } + 20% { + clip-path: inset(30% 0 40% 0); + } + 25% { + clip-path: inset(40% 0 20% 0); + } + 30% { + clip-path: inset(10% 0 60% 0); + } + 35% { + clip-path: inset(15% 0 55% 0); + } + 40% { + clip-path: inset(25% 0 35% 0); + } + 45% { + clip-path: inset(30% 0 40% 0); + } + 50% { + clip-path: inset(20% 0 50% 0); + } + 55% { + clip-path: inset(10% 0 60% 0); + } + 60% { + clip-path: inset(15% 0 55% 0); + } + 65% { + clip-path: inset(25% 0 35% 0); + } + 70% { + clip-path: inset(30% 0 40% 0); + } + 75% { + clip-path: inset(40% 0 20% 0); + } + 80% { + clip-path: inset(20% 0 50% 0); + } + 85% { + clip-path: inset(10% 0 60% 0); + } + 90% { + clip-path: inset(15% 0 55% 0); + } + 95% { + clip-path: inset(25% 0 35% 0); + } + 100% { + clip-path: inset(30% 0 40% 0); + } +} diff --git a/src/content/TextAnimations/GlitchText/GlitchText.vue b/src/content/TextAnimations/GlitchText/GlitchText.vue new file mode 100644 index 0000000..934c41e --- /dev/null +++ b/src/content/TextAnimations/GlitchText/GlitchText.vue @@ -0,0 +1,47 @@ + + + diff --git a/src/demo/TextAnimations/GlitchTextDemo.vue b/src/demo/TextAnimations/GlitchTextDemo.vue new file mode 100644 index 0000000..56e709f --- /dev/null +++ b/src/demo/TextAnimations/GlitchTextDemo.vue @@ -0,0 +1,90 @@ + + +