diff --git a/app/components/home/HomeHero.vue b/app/components/home/HomeHero.vue index 981a6e6..79923bb 100644 --- a/app/components/home/HomeHero.vue +++ b/app/components/home/HomeHero.vue @@ -18,6 +18,7 @@ const heroRef = ref(null) const heroPanelRef = ref(null) const brandNameRef = ref(null) const studioNameRef = ref(null) +const talkBtnRef = ref(null) let cleanupHeroScroll: (() => void) | null = null @@ -112,7 +113,39 @@ const setupHeroScroll = () => { cleanupHeroScroll = () => gsap.ticker.remove(updateHeroPanelScale) } +const onTalkHover = () => { + if (!talkBtnRef.value) return + const origs = talkBtnRef.value.querySelectorAll('.btn-char-orig') + const clones = talkBtnRef.value.querySelectorAll('.btn-char-clone') + const bg = talkBtnRef.value.querySelector('.btn-bg-hover') + + // 背景从底部滑入 (yPercent: 100 -> 0) + gsap.to(bg, { yPercent: 0, duration: 0.4, ease: 'power3.out', overwrite: true }) + + gsap.to(origs, { yPercent: -100, duration: 0.4, stagger: { amount: 0.2, from: 'start' }, ease: 'power3.out', overwrite: true }) + gsap.to(clones, { yPercent: 0, duration: 0.4, stagger: { amount: 0.2, from: 'start' }, ease: 'power3.out', overwrite: true }) +} + +const onTalkLeave = () => { + if (!talkBtnRef.value) return + const origs = talkBtnRef.value.querySelectorAll('.btn-char-orig') + const clones = talkBtnRef.value.querySelectorAll('.btn-char-clone') + const bg = talkBtnRef.value.querySelector('.btn-bg-hover') + + // 背景向下反向滑出回收 (yPercent: 0 -> 100) + gsap.to(bg, { yPercent: 100, duration: 0.4, ease: 'power3.out', overwrite: true }) + + gsap.to(origs, { yPercent: 0, duration: 0.4, stagger: { amount: 0.2, from: 'end' }, ease: 'power3.out', overwrite: true }) + gsap.to(clones, { yPercent: 100, duration: 0.4, stagger: { amount: 0.2, from: 'end' }, ease: 'power3.out', overwrite: true }) +} + onMounted(() => { + if (talkBtnRef.value) { + const clones = talkBtnRef.value.querySelectorAll('.btn-char-clone') + const bg = talkBtnRef.value.querySelector('.btn-bg-hover') + gsap.set(clones, { yPercent: 100 }) + gsap.set(bg, { yPercent: 100 }) + } // 组件挂载时,先将整个 Hero 强行置于屏幕下方,等待外部调用 `play()` 才滑入 if (heroRef.value) gsap.set(heroRef.value, { yPercent: 100 }) // 初始化滚动监听逻辑 @@ -178,8 +211,39 @@ defineExpose({ play }) {{ t('hero.description') }}

-