mirror of
https://github.com/DavidHDev/vue-bits.git
synced 2026-03-07 06:29:30 -07:00
[ FIX ] : ASCIIText Naming & Registry
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
{"name":"CountUp","title":"CountUp","description":"Animated number counter supporting formatting and decimals.","type":"registry:component","add":"when-added","files":[{"type":"registry:component","role":"file","content":"<template>\n <span ref=\"elementRef\" :class=\"className\" />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, onUnmounted, watch, computed, useTemplateRef } from 'vue';\n\ninterface Props {\n to: number;\n from?: number;\n direction?: 'up' | 'down';\n delay?: number;\n duration?: number;\n className?: string;\n startWhen?: boolean;\n separator?: string;\n onStart?: () => void;\n onEnd?: () => void;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n from: 0,\n direction: 'up',\n delay: 0,\n duration: 2,\n className: '',\n startWhen: true,\n separator: ''\n});\n\nconst elementRef = useTemplateRef<HTMLSpanElement>('elementRef');\nconst currentValue = ref(props.direction === 'down' ? props.to : props.from);\nconst isInView = ref(false);\nconst animationId = ref<number | null>(null);\nconst hasStarted = ref(false);\n\nlet intersectionObserver: IntersectionObserver | null = null;\n\nconst damping = computed(() => 20 + 40 * (1 / props.duration));\nconst stiffness = computed(() => 100 * (1 / props.duration));\n\nlet velocity = 0;\nlet startTime = 0;\n\nconst formatNumber = (value: number) => {\n const options = {\n useGrouping: !!props.separator,\n minimumFractionDigits: 0,\n maximumFractionDigits: 0\n };\n\n const formattedNumber = Intl.NumberFormat('en-US', options).format(Number(value.toFixed(0)));\n\n return props.separator ? formattedNumber.replace(/,/g, props.separator) : formattedNumber;\n};\n\nconst updateDisplay = () => {\n if (elementRef.value) {\n elementRef.value.textContent = formatNumber(currentValue.value);\n }\n};\n\nconst springAnimation = (timestamp: number) => {\n if (!startTime) startTime = timestamp;\n\n const target = props.direction === 'down' ? props.from : props.to;\n const current = currentValue.value;\n\n const displacement = target - current;\n const springForce = displacement * stiffness.value;\n const dampingForce = velocity * damping.value;\n const acceleration = springForce - dampingForce;\n\n velocity += acceleration * 0.016; // Assuming 60fps\n currentValue.value += velocity * 0.016;\n\n updateDisplay();\n\n if (Math.abs(displacement) > 0.01 || Math.abs(velocity) > 0.01) {\n animationId.value = requestAnimationFrame(springAnimation);\n } else {\n currentValue.value = target;\n updateDisplay();\n animationId.value = null;\n\n if (props.onEnd) {\n props.onEnd();\n }\n }\n};\n\nconst startAnimation = () => {\n if (hasStarted.value || !isInView.value || !props.startWhen) return;\n\n hasStarted.value = true;\n\n if (props.onStart) {\n props.onStart();\n }\n\n setTimeout(() => {\n startTime = 0;\n velocity = 0;\n animationId.value = requestAnimationFrame(springAnimation);\n }, props.delay * 1000);\n};\n\nconst setupIntersectionObserver = () => {\n if (!elementRef.value) return;\n\n intersectionObserver = new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting && !isInView.value) {\n isInView.value = true;\n startAnimation();\n }\n },\n {\n threshold: 0,\n rootMargin: '0px'\n }\n );\n\n intersectionObserver.observe(elementRef.value);\n};\n\nconst cleanup = () => {\n if (animationId.value) {\n cancelAnimationFrame(animationId.value);\n animationId.value = null;\n }\n\n if (intersectionObserver) {\n intersectionObserver.disconnect();\n intersectionObserver = null;\n }\n};\n\nwatch(\n [() => props.from, () => props.to, () => props.direction],\n () => {\n currentValue.value = props.direction === 'down' ? props.to : props.from;\n updateDisplay();\n hasStarted.value = false;\n },\n { immediate: true }\n);\n\nwatch(\n () => props.startWhen,\n () => {\n if (props.startWhen && isInView.value && !hasStarted.value) {\n startAnimation();\n }\n }\n);\n\nonMounted(() => {\n updateDisplay();\n setupIntersectionObserver();\n});\n\nonUnmounted(() => {\n cleanup();\n});\n</script>\n","path":"CountUp/CountUp.vue","_imports_":[],"registryDependencies":[],"dependencies":[],"devDependencies":[]}],"registryDependencies":[],"dependencies":[],"devDependencies":[],"categories":["Animations"]}
|
||||
{"name":"CountUp","title":"CountUp","description":"Animated number counter supporting formatting and decimals.","type":"registry:component","add":"when-added","files":[{"type":"registry:component","role":"file","content":"<template>\n <span ref=\"elementRef\" :class=\"className\" />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, onUnmounted, watch, computed, useTemplateRef } from 'vue';\n\ninterface Props {\n to: number;\n from?: number;\n direction?: 'up' | 'down';\n delay?: number;\n duration?: number;\n className?: string;\n startWhen?: boolean;\n separator?: string;\n onStart?: () => void;\n onEnd?: () => void;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n from: 0,\n direction: 'up',\n delay: 0,\n duration: 2,\n className: '',\n startWhen: true,\n separator: ''\n});\n\nconst elementRef = useTemplateRef<HTMLSpanElement>('elementRef');\nconst currentValue = ref(props.direction === 'down' ? props.to : props.from);\nconst isInView = ref(false);\nconst animationId = ref<number | null>(null);\nconst hasStarted = ref(false);\n\nlet intersectionObserver: IntersectionObserver | null = null;\n\nconst damping = computed(() => 20 + 40 * (1 / props.duration));\nconst stiffness = computed(() => 100 * (1 / props.duration));\n\nlet velocity = 0;\nlet startTime = 0;\n\nconst formatNumber = (value: number) => {\n const options = {\n useGrouping: !!props.separator,\n minimumFractionDigits: 0,\n maximumFractionDigits: 0\n };\n\n const formattedNumber = Intl.NumberFormat('en-US', options).format(Number(value.toFixed(0)));\n\n return props.separator ? formattedNumber.replace(/,/g, props.separator) : formattedNumber;\n};\n\nconst updateDisplay = () => {\n if (elementRef.value) {\n elementRef.value.textContent = formatNumber(currentValue.value);\n }\n};\n\nconst springAnimation = (timestamp: number) => {\n if (!startTime) startTime = timestamp;\n\n const target = props.direction === 'down' ? props.from : props.to;\n const current = currentValue.value;\n\n const displacement = target - current;\n const springForce = displacement * stiffness.value;\n const dampingForce = velocity * damping.value;\n const acceleration = springForce - dampingForce;\n\n velocity += acceleration * 0.016; // Assuming 60fps\n currentValue.value += velocity * 0.016;\n\n updateDisplay();\n\n if (Math.abs(displacement) > 0.01 || Math.abs(velocity) > 0.01) {\n animationId.value = requestAnimationFrame(springAnimation);\n } else {\n currentValue.value = target;\n updateDisplay();\n animationId.value = null;\n\n if (props.onEnd) {\n props.onEnd();\n }\n }\n};\n\nconst startAnimation = () => {\n if (hasStarted.value || !isInView.value || !props.startWhen) return;\n\n hasStarted.value = true;\n\n if (props.onStart) {\n props.onStart();\n }\n\n setTimeout(() => {\n startTime = 0;\n velocity = 0;\n animationId.value = requestAnimationFrame(springAnimation);\n }, props.delay * 1000);\n};\n\nconst setupIntersectionObserver = () => {\n if (!elementRef.value) return;\n\n intersectionObserver = new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting && !isInView.value) {\n isInView.value = true;\n startAnimation();\n }\n },\n {\n threshold: 0,\n rootMargin: '0px'\n }\n );\n\n intersectionObserver.observe(elementRef.value);\n};\n\nconst cleanup = () => {\n if (animationId.value) {\n cancelAnimationFrame(animationId.value);\n animationId.value = null;\n }\n\n if (intersectionObserver) {\n intersectionObserver.disconnect();\n intersectionObserver = null;\n }\n};\n\nwatch(\n [() => props.from, () => props.to, () => props.direction],\n () => {\n currentValue.value = props.direction === 'down' ? props.to : props.from;\n updateDisplay();\n hasStarted.value = false;\n },\n { immediate: true }\n);\n\nwatch(\n () => props.startWhen,\n () => {\n if (props.startWhen && isInView.value && !hasStarted.value) {\n startAnimation();\n }\n }\n);\n\nonMounted(() => {\n updateDisplay();\n setupIntersectionObserver();\n});\n\nonUnmounted(() => {\n cleanup();\n});\n</script>\n","path":"CountUp/CountUp.vue","_imports_":[],"registryDependencies":[],"dependencies":[],"devDependencies":[]}],"registryDependencies":[],"dependencies":[],"devDependencies":[],"categories":["TextAnimations"]}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
public/r/PixelSnow.json
Normal file
1
public/r/PixelSnow.json
Normal file
File diff suppressed because one or more lines are too long
1
public/r/PixelTrail.json
Normal file
1
public/r/PixelTrail.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
public/r/Shuffle.json
Normal file
1
public/r/Shuffle.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -549,19 +549,19 @@
|
||||
"categories": ["Animations"]
|
||||
},
|
||||
{
|
||||
"name": "CountUp",
|
||||
"title": "CountUp",
|
||||
"description": "Animated number counter supporting formatting and decimals.",
|
||||
"name": "PixelTrail",
|
||||
"title": "PixelTrail",
|
||||
"description": "Pixel grid trail effect that follows cursor movement with customizable gooey filter.",
|
||||
"type": "registry:component",
|
||||
"add": "when-added",
|
||||
"registryDependencies": [],
|
||||
"dependencies": [],
|
||||
"dependencies": [{ "ecosystem": "js", "name": "three", "version": "^0.178.0" }],
|
||||
"devDependencies": [],
|
||||
"files": [
|
||||
{
|
||||
"type": "registry:component",
|
||||
"role": "file",
|
||||
"path": "CountUp/CountUp.vue",
|
||||
"path": "PixelTrail/PixelTrail.vue",
|
||||
"registryDependencies": [],
|
||||
"dependencies": [],
|
||||
"devDependencies": []
|
||||
@@ -582,7 +582,28 @@
|
||||
{
|
||||
"type": "registry:component",
|
||||
"role": "file",
|
||||
"path": "ASCIIText/AsciiText.vue",
|
||||
"path": "ASCIIText/ASCIIText.vue",
|
||||
"registryDependencies": [],
|
||||
"dependencies": [],
|
||||
"devDependencies": []
|
||||
}
|
||||
],
|
||||
"categories": ["TextAnimations"]
|
||||
},
|
||||
{
|
||||
"name": "CountUp",
|
||||
"title": "CountUp",
|
||||
"description": "Animated number counter supporting formatting and decimals.",
|
||||
"type": "registry:component",
|
||||
"add": "when-added",
|
||||
"registryDependencies": [],
|
||||
"dependencies": [],
|
||||
"devDependencies": [],
|
||||
"files": [
|
||||
{
|
||||
"type": "registry:component",
|
||||
"role": "file",
|
||||
"path": "CountUp/CountUp.vue",
|
||||
"registryDependencies": [],
|
||||
"dependencies": [],
|
||||
"devDependencies": []
|
||||
@@ -1010,6 +1031,27 @@
|
||||
],
|
||||
"categories": ["TextAnimations"]
|
||||
},
|
||||
{
|
||||
"name": "Shuffle",
|
||||
"title": "Shuffle",
|
||||
"description": "GSAP-powered slot machine style text shuffle animation with scroll trigger.",
|
||||
"type": "registry:component",
|
||||
"add": "when-added",
|
||||
"registryDependencies": [],
|
||||
"dependencies": [{ "ecosystem": "js", "name": "gsap", "version": "^3.13.0" }],
|
||||
"devDependencies": [],
|
||||
"files": [
|
||||
{
|
||||
"type": "registry:component",
|
||||
"role": "file",
|
||||
"path": "Shuffle/Shuffle.vue",
|
||||
"registryDependencies": [],
|
||||
"dependencies": [],
|
||||
"devDependencies": []
|
||||
}
|
||||
],
|
||||
"categories": ["TextAnimations"]
|
||||
},
|
||||
{
|
||||
"name": "AnimatedList",
|
||||
"title": "AnimatedList",
|
||||
@@ -2391,6 +2433,27 @@
|
||||
}
|
||||
],
|
||||
"categories": ["Backgrounds"]
|
||||
},
|
||||
{
|
||||
"name": "PixelSnow",
|
||||
"title": "PixelSnow",
|
||||
"description": "Falling pixelated snow effect with customizable density and speed.",
|
||||
"type": "registry:component",
|
||||
"add": "when-added",
|
||||
"registryDependencies": [],
|
||||
"dependencies": [{ "ecosystem": "js", "name": "three", "version": "^0.178.0" }],
|
||||
"devDependencies": [],
|
||||
"files": [
|
||||
{
|
||||
"type": "registry:component",
|
||||
"role": "file",
|
||||
"path": "PixelSnow/PixelSnow.vue",
|
||||
"registryDependencies": [],
|
||||
"dependencies": [],
|
||||
"devDependencies": []
|
||||
}
|
||||
],
|
||||
"categories": ["Backgrounds"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ const textAnimations = {
|
||||
'falling-text': () => import("../demo/TextAnimations/FallingTextDemo.vue"),
|
||||
'text-cursor': () => import("../demo/TextAnimations/TextCursorDemo.vue"),
|
||||
'decrypted-text': () => import("../demo/TextAnimations/DecryptedTextDemo.vue"),
|
||||
'ascii-text': () => import("../demo/TextAnimations/AsciiTextDemo.vue"),
|
||||
'ascii-text': () => import("../demo/TextAnimations/ASCIITextDemo.vue"),
|
||||
'scramble-text': () => import("../demo/TextAnimations/ScrambleTextDemo.vue"),
|
||||
'true-focus': () => import("../demo/TextAnimations/TrueFocusDemo.vue"),
|
||||
'scroll-float': () => import("../demo/TextAnimations/ScrollFloatDemo.vue"),
|
||||
|
||||
@@ -225,11 +225,11 @@ export const componentMetadata: ComponentMetadata = {
|
||||
|
||||
//! Text Animations -------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
'TextAnimations/AsciiText': {
|
||||
'TextAnimations/ASCIIText': {
|
||||
videoUrl: '/assets/videos/asciitext.webm',
|
||||
description: 'Renders text with an animated ASCII background for a retro feel.',
|
||||
category: 'TextAnimations',
|
||||
name: 'AsciiText',
|
||||
name: 'ASCIIText',
|
||||
docsUrl: 'https://vue-bits.dev/text-animations/ascii-text',
|
||||
tags: []
|
||||
},
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import code from '@/content/TextAnimations/AsciiText/AsciiText.vue?raw';
|
||||
import code from '@/content/TextAnimations/ASCIIText/ASCIIText.vue?raw';
|
||||
import { createCodeObject } from '../../../types/code';
|
||||
|
||||
export const asciiText = createCodeObject(code, 'TextAnimations/AsciiText', {
|
||||
export const asciiText = createCodeObject(code, 'TextAnimations/ASCIIText', {
|
||||
installation: `npm install three @types/three`,
|
||||
usage: `<!-- Component ported and enhanced from https://codepen.io/JuanFuentes/pen/eYEeoyE -->
|
||||
|
||||
<template>
|
||||
<AsciiText
|
||||
<ASCIIText
|
||||
text="Hey!"
|
||||
:ascii-font-size="8"
|
||||
:text-font-size="200"
|
||||
@@ -18,6 +18,6 @@ export const asciiText = createCodeObject(code, 'TextAnimations/AsciiText', {
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import AsciiText from "./AsciiText.vue";
|
||||
import ASCIIText from "./ASCIIText.vue";
|
||||
</script>`
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import { onMounted, onUnmounted, watch, useTemplateRef } from 'vue';
|
||||
import * as THREE from 'three';
|
||||
|
||||
interface AsciiTextProps {
|
||||
interface ASCIITextProps {
|
||||
text?: string;
|
||||
asciiFontSize?: number;
|
||||
textFontSize?: number;
|
||||
@@ -14,7 +14,7 @@ interface AsciiTextProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<AsciiTextProps>(), {
|
||||
const props = withDefaults(defineProps<ASCIITextProps>(), {
|
||||
text: 'David!',
|
||||
asciiFontSize: 8,
|
||||
textFontSize: 200,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<TabbedLayout>
|
||||
<template #preview>
|
||||
<div class="demo-container h-[400px] overflow-hidden">
|
||||
<AsciiText
|
||||
<ASCIIText
|
||||
:key="rerenderKey"
|
||||
:text="text"
|
||||
:ascii-font-size="asciiFontSize"
|
||||
@@ -62,7 +62,7 @@ import Customize from '@/components/common/Customize.vue';
|
||||
import PreviewSlider from '@/components/common/PreviewSlider.vue';
|
||||
import PreviewSwitch from '@/components/common/PreviewSwitch.vue';
|
||||
import PreviewText from '@/components/common/PreviewText.vue';
|
||||
import AsciiText from '@/content/TextAnimations/AsciiText/AsciiText.vue';
|
||||
import ASCIIText from '@/content/TextAnimations/ASCIIText/ASCIIText.vue';
|
||||
import { asciiText } from '@/constants/code/TextAnimations/asciiTextCode';
|
||||
import { useForceRerender } from '@/composables/useForceRerender';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user