修复移动端报错:替换 closest 为 parentElement
- closest 在旧版 WebView 中可能不支持导致脚本中断 - 改用 parentElement 更安全高效 - 修复后数字视差逻辑应正常执行
This commit is contained in:
parent
a22c465a3b
commit
624bb422bb
69
index.html
69
index.html
|
|
@ -365,26 +365,25 @@
|
||||||
opacity: 0.08;
|
opacity: 0.08;
|
||||||
transition: opacity 0.7s cubic-bezier(0.16, 1, 0.3, 1);
|
transition: opacity 0.7s cubic-bezier(0.16, 1, 0.3, 1);
|
||||||
}
|
}
|
||||||
/* 内容元素默认在下方(准备从下往上滑入) */
|
/* 内容元素默认在更下方(准备从下往上大幅滑入) */
|
||||||
#pain-points .pain-item .pain-icon,
|
#pain-points .pain-item .pain-icon,
|
||||||
#pain-points .pain-item h3,
|
#pain-points .pain-item h3,
|
||||||
#pain-points .pain-item p {
|
#pain-points .pain-item p {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(40px);
|
transform: translateY(60px);
|
||||||
transition: opacity 0.7s cubic-bezier(0.16, 1, 0.3, 1),
|
transition: opacity 0.8s cubic-bezier(0.16, 1, 0.3, 1),
|
||||||
transform 0.7s 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 {
|
#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 {
|
#pain-points .pain-item .pain-num {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(-70px);
|
transition: opacity 1s ease;
|
||||||
transition: opacity 0.9s ease, transform 0.8s cubic-bezier(0.16, 1, 0.3, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 进入视口后:内容上移,数字下落 */
|
/* 进入视口后:内容上移,数字反向坠落 */
|
||||||
#pain-points .pain-item.in-view {
|
#pain-points .pain-item.in-view {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
@ -396,17 +395,18 @@
|
||||||
#pain-points .pain-item.in-view h3 {
|
#pain-points .pain-item.in-view h3 {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
transition-delay: 0.12s;
|
transition-delay: 0.1s;
|
||||||
}
|
}
|
||||||
#pain-points .pain-item.in-view p {
|
#pain-points .pain-item.in-view p {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
transition-delay: 0.2s;
|
transition-delay: 0.18s;
|
||||||
}
|
}
|
||||||
|
/* 数字:越落越清晰 */
|
||||||
#pain-points .pain-item.in-view .pain-num {
|
#pain-points .pain-item.in-view .pain-num {
|
||||||
opacity: 0.15;
|
opacity: 0.3;
|
||||||
transform: translateY(0);
|
/* transform 完全由 JS 视差逻辑接管 */
|
||||||
transition-delay: 0.08s;
|
transition-delay: 0.02s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 思路板块同样 */
|
/* 思路板块同样 */
|
||||||
|
|
@ -563,7 +563,7 @@
|
||||||
right: 30px;
|
right: 30px;
|
||||||
font-size: 110px;
|
font-size: 110px;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
color: rgba(255,255,255,0.08);
|
color: rgba(255,255,255,0.2);
|
||||||
letter-spacing: -5px;
|
letter-spacing: -5px;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
@ -952,8 +952,9 @@
|
||||||
}, { threshold: 0.15, rootMargin: "0px 0px -50px 0px" });
|
}, { threshold: 0.15, rootMargin: "0px 0px -50px 0px" });
|
||||||
document.querySelectorAll('.fade-up').forEach(el => observer.observe(el));
|
document.querySelectorAll('.fade-up').forEach(el => observer.observe(el));
|
||||||
|
|
||||||
// 移动端:轻量级 IntersectionObserver(入场错位动画由 CSS transition 处理)
|
// 移动端:入场动画 + 视差滚动
|
||||||
if (window.innerWidth <= 900) {
|
if (window.innerWidth <= 900) {
|
||||||
|
// 1. 入场动画(一次性)
|
||||||
const mobileItems = document.querySelectorAll('#pain-points .pain-item, #approach .approach-item');
|
const mobileItems = document.querySelectorAll('#pain-points .pain-item, #approach .approach-item');
|
||||||
const mobileObserver = new IntersectionObserver((entries) => {
|
const mobileObserver = new IntersectionObserver((entries) => {
|
||||||
entries.forEach(entry => {
|
entries.forEach(entry => {
|
||||||
|
|
@ -961,6 +962,42 @@
|
||||||
});
|
});
|
||||||
}, { threshold: 0.05, rootMargin: "0px 0px -5% 0px" });
|
}, { threshold: 0.05, rootMargin: "0px 0px -5% 0px" });
|
||||||
mobileItems.forEach(item => mobileObserver.observe(item));
|
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();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue