refactor(页面动画): 优化首页动画元素引用和初始化逻辑
移除未使用的 introCharRefs 引用,改用 gsap.utils.toArray 获取字符元素 将 '.hero-intro-tm' 选择器结果缓存为 tmElement 避免重复查询 为静态元素添加 v-once 指令提升性能 调整部分元素的初始 opacity 和 visibility 状态
This commit is contained in:
+14
-10
@@ -54,7 +54,6 @@ const loaderRef = ref<HTMLElement | null>(null)
|
||||
const loaderBarRef = ref<HTMLElement | null>(null)
|
||||
const introRef = ref<HTMLElement | null>(null)
|
||||
const introTitleRef = ref<HTMLElement | null>(null)
|
||||
const introCharRefs = ref<HTMLElement[]>([])
|
||||
const heroStageRef = ref<HTMLElement | null>(null)
|
||||
const heroRef = ref<HTMLElement | null>(null)
|
||||
const heroPanelRef = ref<HTMLElement | null>(null)
|
||||
@@ -96,8 +95,9 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
const introCharElements = gsap.utils.toArray('.hero-intro-char', introElement)
|
||||
const tmElement = introElement.querySelector('.hero-intro-tm')
|
||||
|
||||
if (introCharElements.length === 0) {
|
||||
if (introCharElements.length === 0 || !tmElement) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -210,10 +210,10 @@ onMounted(() => {
|
||||
y: 0,
|
||||
autoAlpha: 1,
|
||||
})
|
||||
.set('.hero-intro-tm', {
|
||||
.set(tmElement, {
|
||||
autoAlpha: 0,
|
||||
})
|
||||
.fromTo(gsap.utils.toArray('.hero-intro-char', introElement), {
|
||||
.fromTo(introCharElements, {
|
||||
yPercent: 110,
|
||||
y: 0,
|
||||
}, {
|
||||
@@ -222,7 +222,7 @@ onMounted(() => {
|
||||
duration: 0.75,
|
||||
stagger: 0.055,
|
||||
})
|
||||
.to('.hero-intro-tm', {
|
||||
.to(tmElement, {
|
||||
autoAlpha: 1,
|
||||
duration: 0.4,
|
||||
ease: 'power2.out',
|
||||
@@ -271,7 +271,7 @@ onMounted(() => {
|
||||
gsap.set(introTitleElement, { y: 0, autoAlpha: 1 })
|
||||
// 强制清除 CSS 中的 translateY 像素值,避免被 GSAP 解析为固定 y 像素导致一直不可见
|
||||
gsap.set(introCharElements, { y: 0, yPercent: 110 })
|
||||
gsap.set('.hero-intro-tm', { autoAlpha: 0 })
|
||||
gsap.set(tmElement, { autoAlpha: 0 })
|
||||
gsap.set(heroElement, { yPercent: 100 })
|
||||
if (topHeader) {
|
||||
gsap.set(topHeader, { yPercent: -140, autoAlpha: 0 })
|
||||
@@ -336,7 +336,7 @@ onBeforeUnmount(() => {
|
||||
:data-demo-user="demoUserName"
|
||||
:data-demo-user-role="demoUserRole"
|
||||
>
|
||||
<div ref="loaderRef" class="page-loader" aria-hidden="true">
|
||||
<div ref="loaderRef" class="page-loader" aria-hidden="true" v-once>
|
||||
<div class="page-loader-content">
|
||||
<p>Loading</p>
|
||||
<span class="page-loader-line">
|
||||
@@ -346,14 +346,14 @@ onBeforeUnmount(() => {
|
||||
</div>
|
||||
|
||||
<div ref="introRef" class="hero-intro" aria-hidden="true">
|
||||
<h1 ref="introTitleRef" class="hero-intro-title" :aria-label="introTitle">
|
||||
<h1 ref="introTitleRef" class="hero-intro-title" :aria-label="introTitle" v-once>
|
||||
<span class="hero-intro-word">
|
||||
<span
|
||||
v-for="(letter, index) in introLetters"
|
||||
:key="`${letter}-${index}`"
|
||||
class="hero-intro-char-wrap"
|
||||
>
|
||||
<span ref="introCharRefs" class="hero-intro-char">{{ letter }}</span>
|
||||
<span class="hero-intro-char">{{ letter }}</span>
|
||||
</span>
|
||||
<span class="hero-intro-tm">TM</span>
|
||||
</span>
|
||||
@@ -365,7 +365,7 @@ onBeforeUnmount(() => {
|
||||
class="hero-stage"
|
||||
:style="{ '--hero-pin-distance': `${heroPinDistance}px` }"
|
||||
>
|
||||
<section ref="heroRef" class="hero-section">
|
||||
<section ref="heroRef" class="hero-section" v-once>
|
||||
<div class="hero-backdrop" aria-hidden="true">
|
||||
<div
|
||||
v-for="column in heroGalleryColumns"
|
||||
@@ -455,6 +455,8 @@ onBeforeUnmount(() => {
|
||||
overflow: hidden;
|
||||
color: #fff;
|
||||
background: #000;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
@@ -495,6 +497,8 @@ onBeforeUnmount(() => {
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 1;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.hero-stage {
|
||||
|
||||
Reference in New Issue
Block a user