Issue resolved

Signed-off-by: zubairrafi <walleeva2018@gmail.com>
This commit is contained in:
zubairrafi
2025-07-12 11:26:58 +06:00
parent ea8a04eb3b
commit 936bca258a
3 changed files with 118 additions and 138 deletions

View File

@@ -1,141 +1,123 @@
<template>
<h2 ref="containerRef" :class="`scroll-float ${containerClassName}`">
<span :class="`scroll-float-text ${textClassName}`">
<span
v-for="(char, index) in splitText"
:key="index"
class="char"
>
{{ char === " " ? "\u00A0" : char }}
</span>
<h2 ref="containerRef" :class="`overflow-hidden ${containerClassName}`">
<span :class="`inline-block text-center leading-relaxed font-black ${textClassName}`" style="font-size: clamp(1.6rem, 8vw, 10rem);">
<span
v-for="(char, index) in splitText"
:key="index"
class="inline-block char"
>
{{ char === " " ? "\u00A0" : char }}
</span>
</h2>
</template>
<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted, watch } from 'vue';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);
interface Props {
children: string;
scrollContainerRef?: { current: HTMLElement | null };
containerClassName?: string;
textClassName?: string;
animationDuration?: number;
ease?: string;
scrollStart?: string;
scrollEnd?: string;
stagger?: number;
</span>
</h2>
</template>
<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted, watch } from 'vue';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);
interface Props {
children: string;
scrollContainerRef?: { current: HTMLElement | null };
containerClassName?: string;
textClassName?: string;
animationDuration?: number;
ease?: string;
scrollStart?: string;
scrollEnd?: string;
stagger?: number;
}
const props = withDefaults(defineProps<Props>(), {
containerClassName: '',
textClassName: '',
animationDuration: 1,
ease: 'back.inOut(2)',
scrollStart: 'center bottom+=50%',
scrollEnd: 'bottom bottom-=40%',
stagger: 0.03
});
const containerRef = ref<HTMLElement | null>(null);
let scrollTriggerInstance: ScrollTrigger | null = null;
const splitText = computed(() => {
const text = typeof props.children === 'string' ? props.children : '';
return text.split("");
});
const initializeAnimation = () => {
const el = containerRef.value;
if (!el) return;
const scroller =
props.scrollContainerRef && props.scrollContainerRef.current
? props.scrollContainerRef.current
: window;
const charElements = el.querySelectorAll('.char');
if (scrollTriggerInstance) {
scrollTriggerInstance.kill();
}
const props = withDefaults(defineProps<Props>(), {
containerClassName: '',
textClassName: '',
animationDuration: 1,
ease: 'back.inOut(2)',
scrollStart: 'center bottom+=50%',
scrollEnd: 'bottom bottom-=40%',
stagger: 0.03
});
const containerRef = ref<HTMLElement | null>(null);
let scrollTriggerInstance: ScrollTrigger | null = null;
const splitText = computed(() => {
const text = typeof props.children === 'string' ? props.children : '';
return text.split("");
});
const initializeAnimation = () => {
const el = containerRef.value;
if (!el) return;
const scroller =
props.scrollContainerRef && props.scrollContainerRef.current
? props.scrollContainerRef.current
: window;
const charElements = el.querySelectorAll('.char');
if (scrollTriggerInstance) {
scrollTriggerInstance.kill();
}
const tl = gsap.fromTo(
charElements,
{
willChange: 'opacity, transform',
opacity: 0,
yPercent: 120,
scaleY: 2.3,
scaleX: 0.7,
transformOrigin: '50% 0%'
},
{
duration: props.animationDuration,
ease: props.ease,
opacity: 1,
yPercent: 0,
scaleY: 1,
scaleX: 1,
stagger: props.stagger,
scrollTrigger: {
trigger: el,
scroller,
start: props.scrollStart,
end: props.scrollEnd,
scrub: true
}
}
);
scrollTriggerInstance = tl.scrollTrigger || null;
};
onMounted(() => {
initializeAnimation();
});
onUnmounted(() => {
if (scrollTriggerInstance) {
scrollTriggerInstance.kill();
}
});
watch(
[
() => props.children,
() => props.scrollContainerRef,
() => props.animationDuration,
() => props.ease,
() => props.scrollStart,
() => props.scrollEnd,
() => props.stagger
],
() => {
initializeAnimation();
const tl = gsap.fromTo(
charElements,
{
willChange: 'opacity, transform',
opacity: 0,
yPercent: 120,
scaleY: 2.3,
scaleX: 0.7,
transformOrigin: '50% 0%'
},
{ deep: true }
{
duration: props.animationDuration,
ease: props.ease,
opacity: 1,
yPercent: 0,
scaleY: 1,
scaleX: 1,
stagger: props.stagger,
scrollTrigger: {
trigger: el,
scroller,
start: props.scrollStart,
end: props.scrollEnd,
scrub: true
}
}
);
</script>
<style scoped>
.scroll-float {
overflow: hidden;
scrollTriggerInstance = tl.scrollTrigger || null;
};
onMounted(() => {
initializeAnimation();
});
onUnmounted(() => {
if (scrollTriggerInstance) {
scrollTriggerInstance.kill();
}
.scroll-float-text {
display: inline-block;
font-size: clamp(1.6rem, 8vw, 10rem);
font-weight: 900;
text-align: center;
line-height: 1.5;
}
.char {
display: inline-block;
}
</style>
});
watch(
[
() => props.children,
() => props.scrollContainerRef,
() => props.animationDuration,
() => props.ease,
() => props.scrollStart,
() => props.scrollEnd,
() => props.stagger
],
() => {
initializeAnimation();
},
{ deep: true }
);
</script>