mirror of
https://github.com/DavidHDev/vue-bits.git
synced 2026-03-07 06:29:30 -07:00
1 line
4.5 KiB
JSON
1 line
4.5 KiB
JSON
{"name":"GlitchText","title":"GlitchText","description":"RGB split and distortion glitch effect with jitter effects.","type":"registry:component","add":"when-added","files":[{"type":"registry:component","role":"file","content":"<template>\n <div :class=\"computedClasses\" :style=\"inlineStyles\" :data-text=\"children\">\n {{ children }}\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport type { CSSProperties } from 'vue';\n\ninterface GlitchTextProps {\n children: string;\n speed?: number;\n enableShadows?: boolean;\n enableOnHover?: boolean;\n className?: string;\n}\n\ninterface CustomCSSProperties extends CSSProperties {\n '--after-duration': string;\n '--before-duration': string;\n '--after-shadow': string;\n '--before-shadow': string;\n}\n\nconst props = withDefaults(defineProps<GlitchTextProps>(), {\n speed: 0.5,\n enableShadows: true,\n enableOnHover: false,\n className: ''\n});\n\nconst inlineStyles = computed(\n (): CustomCSSProperties => ({\n '--after-duration': `${props.speed * 3}s`,\n '--before-duration': `${props.speed * 2}s`,\n '--after-shadow': props.enableShadows ? '-5px 0 red' : 'none',\n '--before-shadow': props.enableShadows ? '5px 0 cyan' : 'none'\n })\n);\n\nconst baseClasses = [\n 'text-white',\n 'font-black',\n 'whitespace-nowrap',\n 'relative',\n 'mx-auto',\n 'select-none',\n 'cursor-pointer',\n 'text-[clamp(2rem,10vw,8rem)]',\n\n 'before:content-[attr(data-text)]',\n 'before:absolute',\n 'before:top-0',\n 'before:text-white',\n 'before:bg-[#0b0b0b]',\n 'before:overflow-hidden',\n 'before:[clip-path:inset(0_0_0_0)]',\n\n 'after:content-[attr(data-text)]',\n 'after:absolute',\n 'after:top-0',\n 'after:text-white',\n 'after:bg-[#0b0b0b]',\n 'after:overflow-hidden',\n 'after:[clip-path:inset(0_0_0_0)]'\n];\n\nconst normalGlitchClasses = [\n 'after:left-[10px]',\n 'after:[text-shadow:var(--after-shadow,-10px_0_red)]',\n 'after:[animation:animate-glitch_var(--after-duration,3s)_infinite_linear_alternate-reverse]',\n\n 'before:left-[-10px]',\n 'before:[text-shadow:var(--before-shadow,10px_0_cyan)]',\n 'before:[animation:animate-glitch_var(--before-duration,2s)_infinite_linear_alternate-reverse]'\n];\n\nconst hoverOnlyClasses = [\n 'before:content-[\"\"]',\n 'before:opacity-0',\n 'before:[animation:none]',\n 'after:content-[\"\"]',\n 'after:opacity-0',\n 'after:[animation:none]',\n\n 'hover:before:content-[attr(data-text)]',\n 'hover:before:opacity-100',\n 'hover:before:left-[-10px]',\n 'hover:before:[text-shadow:var(--before-shadow,10px_0_cyan)]',\n 'hover:before:[animation:animate-glitch_var(--before-duration,2s)_infinite_linear_alternate-reverse]',\n\n 'hover:after:content-[attr(data-text)]',\n 'hover:after:opacity-100',\n 'hover:after:left-[10px]',\n 'hover:after:[text-shadow:var(--after-shadow,-10px_0_red)]',\n 'hover:after:[animation:animate-glitch_var(--after-duration,3s)_infinite_linear_alternate-reverse]'\n];\n\nconst computedClasses = computed(() => {\n const classes = [...baseClasses];\n\n if (props.enableOnHover) {\n classes.push(...hoverOnlyClasses);\n } else {\n classes.push(...normalGlitchClasses);\n }\n\n if (props.className) {\n classes.push(props.className);\n }\n\n return classes.join(' ');\n});\n</script>\n\n<style>\n@keyframes animate-glitch {\n 0% {\n clip-path: inset(20% 0 50% 0);\n }\n 5% {\n clip-path: inset(10% 0 60% 0);\n }\n 10% {\n clip-path: inset(15% 0 55% 0);\n }\n 15% {\n clip-path: inset(25% 0 35% 0);\n }\n 20% {\n clip-path: inset(30% 0 40% 0);\n }\n 25% {\n clip-path: inset(40% 0 20% 0);\n }\n 30% {\n clip-path: inset(10% 0 60% 0);\n }\n 35% {\n clip-path: inset(15% 0 55% 0);\n }\n 40% {\n clip-path: inset(25% 0 35% 0);\n }\n 45% {\n clip-path: inset(30% 0 40% 0);\n }\n 50% {\n clip-path: inset(20% 0 50% 0);\n }\n 55% {\n clip-path: inset(10% 0 60% 0);\n }\n 60% {\n clip-path: inset(15% 0 55% 0);\n }\n 65% {\n clip-path: inset(25% 0 35% 0);\n }\n 70% {\n clip-path: inset(30% 0 40% 0);\n }\n 75% {\n clip-path: inset(40% 0 20% 0);\n }\n 80% {\n clip-path: inset(20% 0 50% 0);\n }\n 85% {\n clip-path: inset(10% 0 60% 0);\n }\n 90% {\n clip-path: inset(15% 0 55% 0);\n }\n 95% {\n clip-path: inset(25% 0 35% 0);\n }\n 100% {\n clip-path: inset(30% 0 40% 0);\n }\n}\n</style>\n","path":"GlitchText/GlitchText.vue","_imports_":[],"registryDependencies":[],"dependencies":[],"devDependencies":[]}],"registryDependencies":[],"dependencies":[],"devDependencies":[],"categories":["TextAnimations"]} |