diff --git a/index.html b/index.html index 605093c..e44ec46 100644 --- a/index.html +++ b/index.html @@ -365,26 +365,25 @@ opacity: 0.08; transition: opacity 0.7s cubic-bezier(0.16, 1, 0.3, 1); } - /* 内容元素默认在下方(准备从下往上滑入) */ + /* 内容元素默认在更下方(准备从下往上大幅滑入) */ #pain-points .pain-item .pain-icon, #pain-points .pain-item h3, #pain-points .pain-item p { opacity: 0; - transform: translateY(40px); - transition: opacity 0.7s cubic-bezier(0.16, 1, 0.3, 1), - transform 0.7s cubic-bezier(0.16, 1, 0.3, 1); + transform: translateY(60px); + transition: opacity 0.8s cubic-bezier(0.16, 1, 0.3, 1), + transform 0.8s cubic-bezier(0.16, 1, 0.3, 1); } #pain-points .pain-item .pain-icon { - transform: scale(0.6) translateY(40px); + transform: scale(0.6) translateY(60px); } - /* 数字默认在上方(准备从上往下滑入) */ + /* 数字:默认状态由 JS 控制,这里不设 transform 避免冲突 */ #pain-points .pain-item .pain-num { opacity: 0; - transform: translateY(-70px); - transition: opacity 0.9s ease, transform 0.8s cubic-bezier(0.16, 1, 0.3, 1); + transition: opacity 1s ease; } - /* 进入视口后:内容上移,数字下落 */ + /* 进入视口后:内容上移,数字反向坠落 */ #pain-points .pain-item.in-view { opacity: 1; } @@ -396,17 +395,18 @@ #pain-points .pain-item.in-view h3 { opacity: 1; transform: translateY(0); - transition-delay: 0.12s; + transition-delay: 0.1s; } #pain-points .pain-item.in-view p { opacity: 1; transform: translateY(0); - transition-delay: 0.2s; + transition-delay: 0.18s; } + /* 数字:越落越清晰 */ #pain-points .pain-item.in-view .pain-num { - opacity: 0.15; - transform: translateY(0); - transition-delay: 0.08s; + opacity: 0.3; + /* transform 完全由 JS 视差逻辑接管 */ + transition-delay: 0.02s; } /* 思路板块同样 */ @@ -563,7 +563,7 @@ right: 30px; font-size: 110px; font-weight: 900; - color: rgba(255,255,255,0.08); + color: rgba(255,255,255,0.2); letter-spacing: -5px; line-height: 1; } @@ -952,8 +952,9 @@ }, { threshold: 0.15, rootMargin: "0px 0px -50px 0px" }); document.querySelectorAll('.fade-up').forEach(el => observer.observe(el)); - // 移动端:轻量级 IntersectionObserver(入场错位动画由 CSS transition 处理) + // 移动端:入场动画 + 视差滚动 if (window.innerWidth <= 900) { + // 1. 入场动画(一次性) const mobileItems = document.querySelectorAll('#pain-points .pain-item, #approach .approach-item'); const mobileObserver = new IntersectionObserver((entries) => { entries.forEach(entry => { @@ -961,6 +962,42 @@ }); }, { threshold: 0.05, rootMargin: "0px 0px -5% 0px" }); mobileItems.forEach(item => mobileObserver.observe(item)); + + // 2. 数字编号滚动视差(基于卡片相对视口位置) + let ticking = false; + const painNums = document.querySelectorAll('#pain-points .pain-num'); + + function updateParallax() { + painNums.forEach(num => { + // 获取数字所在的父卡片(.pain-item) + const card = num.parentElement; + if (!card) return; + + // 计算卡片相对于视口顶部的距离 + const rect = card.getBoundingClientRect(); + + // 核心视差逻辑: + // rect.top 越大(卡片在屏幕越下方),位移越大(向上推数字) + // 随着卡片向上滚动(rect.top 变小),数字向下回落 + // 这会产生数字比文字"慢半拍"的悬浮感 + // 速度因子 0.15 意味着视差幅度为卡片移动距离的 15% + const speed = 0.15; + const yOffset = -(rect.top * speed); + + num.style.transform = `translateY(${yOffset}px)`; + }); + ticking = false; + } + + window.addEventListener('scroll', () => { + if (!ticking) { + requestAnimationFrame(updateParallax); + ticking = true; + } + }, { passive: true }); + + // 初始化一次 + updateParallax(); }