mirror of
https://github.com/DavidHDev/vue-bits.git
synced 2026-03-07 22:49:31 -07:00
feat(text-animations): add GlitchText component
This commit is contained in:
120
src/content/TextAnimations/GlitchText/GlitchText.css
Normal file
120
src/content/TextAnimations/GlitchText/GlitchText.css
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
47
src/content/TextAnimations/GlitchText/GlitchText.vue
Normal file
47
src/content/TextAnimations/GlitchText/GlitchText.vue
Normal file
@@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<div :class="computedClasses" :style="inlineStyles" :data-text="children">
|
||||
{{ children }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import type { CSSProperties } from 'vue';
|
||||
import './GlitchText.css';
|
||||
|
||||
interface GlitchTextProps {
|
||||
children: string;
|
||||
speed?: number;
|
||||
enableShadows?: boolean;
|
||||
enableOnHover?: boolean;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
interface CustomCSSProperties extends CSSProperties {
|
||||
'--after-duration': string;
|
||||
'--before-duration': string;
|
||||
'--after-shadow': string;
|
||||
'--before-shadow': string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<GlitchTextProps>(), {
|
||||
speed: 0.5,
|
||||
enableShadows: true,
|
||||
enableOnHover: false,
|
||||
className: ''
|
||||
});
|
||||
|
||||
const inlineStyles = computed(
|
||||
(): CustomCSSProperties => ({
|
||||
'--after-duration': `${props.speed * 3}s`,
|
||||
'--before-duration': `${props.speed * 2}s`,
|
||||
'--after-shadow': props.enableShadows ? '-5px 0 red' : 'none',
|
||||
'--before-shadow': props.enableShadows ? '5px 0 cyan' : 'none'
|
||||
})
|
||||
);
|
||||
|
||||
const computedClasses = computed(() => {
|
||||
const hoverClass = props.enableOnHover ? 'enable-on-hover' : '';
|
||||
return `glitch ${hoverClass} ${props.className}`.trim();
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user