基于JavaScript实现仅X轴方向的视差元素效果
X轴鼠标视差效果实现方案
核心问题解答
1. 鼠标移动事件监听对象
- 优先监听
document:只要鼠标在页面内移动就触发视差效果,避免鼠标移出目标区域后效果中断,适配全局视差场景。 - 仅需特定区域生效时:监听
.hero-section元素,仅当鼠标处于该区域内时触发视差。
2. 元素位置计算公式
核心逻辑是将鼠标位置转换为相对视口中心的偏移比例,再乘以自定义视差强度,实现不同层级元素的差异化移动:
- 计算鼠标相对于视口中心的X轴偏移量:
const mouseXOffset = e.clientX - window.innerWidth / 2; - 将偏移量转换为正负比例值(表示左右方向):
const offsetRatio = mouseXOffset / window.innerWidth; - 为不同层级元素设置差异化视差强度,计算最终X轴偏移:
// 近景元素(如iPhone)偏移幅度大 const iphoneTranslate = offsetRatio * 20; // 远景元素(如背景文字)偏移幅度小,可反向移动 const textTranslate = offsetRatio * -5;
注:强度值可根据视觉需求调整,正负号控制移动方向
3. 添加缓动效果
通过requestAnimationFrame结合差值计算实现平滑过渡,避免鼠标停止时元素突然静止:
- 定义变量存储元素当前偏移值,初始为0
- 每次动画帧中,计算当前值与目标值的差值,仅向目标值靠近一部分(缓动系数建议0.1-0.2)
完整实现代码
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <div class="container"> <div class="hero-section"> <div class="hero-section-text-holder"> <div class="hero-section-sticky"> <div class="hero-sticky-holder"> <div class="hero-text-holder"> <div class="hero-text-wrapper _01"> <div class="hero-text">Test1</div> <div class="hero-text-blur">Test1</div> </div> <div class="hero-text-wrapper _02"> <div class="hero-text _02">Test2</div> <div class="hero-text-blur">Test2</div> </div> </div> </div> </div> <div class="iphone-holder"> <img src="https://cdn.prod.website-files.com/63aee5793ca698452efe7f60/63aefb47917c0cfa0943fc97_iPhone%2014%20Pro%20%E2%80%93%20Space%20Black.webp" loading="lazy" sizes="(max-width: 767px) 196.6796875px, 295.015625px" srcset="https://assets.website-files.com/63aee5793ca698452efe7f60/63aefb47917c0cfa0943fc97_iPhone%2014%20Pro%20%E2%80%93%20Space%20Black-p-500.webp 500w, https://assets.website-files.com/63aee5793ca698452efe7f60/63aefb47917c0cfa0943fc97_iPhone%2014%20Pro%20%E2%80%93%20Space%20Black.webp 800w" alt="" class="iphone-image"> <div class="iphone-screen"> <img src="https://cdn.prod.website-files.com/63aee5793ca698452efe7f60/63aefd2632bfdbf4073fa431_Hero%20Iphone%20Image.webp" loading="lazy" alt="" sizes="(max-width: 479px) 80vw, 267.875px" srcset="https://cdn.prod.website-files.com/63aee5793ca698452efe7f60/63aefd2632bfdbf4073fa431_Hero%20Iphone%20Image-p-500.webp 500w, https://cdn.prod.website-files.com/63aee5793ca698452efe7f60/63aefd2632bfdbf4073fa431_Hero%20Iphone%20Image.webp 729w" class="iphone-screen-image"> </div> <div class="iphone-drop-shadow"></div> </div> </div> </div> </div>
CSS
body { color: #fff; background-color: #000; font-family: Manrope, sans-serif; font-size: 14px; line-height: 1.2; } .container { padding: 40px; } img { max-width: 100%; vertical-align: middle; display: inline-block; } .hero-section { flex-direction: column; justify-content: space-between; align-items: center; display: flex; } .hero-section-text-holder { width: 100%; height: 130vh; flex-direction: column; align-items: center; display: flex; } .hero-section-sticky { width: 100%; position: -webkit-sticky; position: sticky; top: 50%; } .hero-sticky-holder { width: 100%; flex-direction: column; justify-content: center; align-items: center; display: flex; } .hero-text-holder { grid-column-gap: 60px; perspective: 1000px; white-space: nowrap; flex-direction: row; justify-content: center; align-items: center; display: flex; position: absolute; } .hero-text-wrapper { justify-content: center; align-items: center; display: flex; } .hero-text { -webkit-text-fill-color: transparent; background-image: linear-gradient(to right, #eec5bd, #f3b1a5 35%, #c6caf6 72%, #dad9e9); -webkit-background-clip: text; background-clip: text; font-size: 14vw; font-weight: 800; } .hero-text-blur { opacity: .64; filter: blur(120px); -webkit-text-fill-color: transparent; background-image: linear-gradient(to right, #eec5bd, #f3b1a5 35%, #c6caf6 72%, #dad9e9); -webkit-background-clip: text; background-clip: text; font-size: 14vw; font-weight: 800; position: absolute; } .hero-text._02 { background-image: linear-gradient(to right, #eec5bd, #f3b1a5 6%, #c6caf6 61%, #dad9e9 72%); } .iphone-holder { z-index: 1; height: 600px; border-radius: 60px; flex-direction: column; justify-content: center; align-items: center; display: flex; position: relative; top: 6%; will-change: transform; } .iphone-screen { z-index: 1; flex-direction: column; justify-content: flex-start; align-items: center; padding: 4.1% 4.6%; display: flex; position: absolute; top: 0%; bottom: 0%; left: 0%; right: 0%; } .iphone-screen-image { width: 100%; height: 100%; object-fit: cover; object-position: 50% 0%; border-radius: 25px; } .iphone-image { z-index: 2; height: 100%; position: relative; } .iphone-drop-shadow { width: 120%; height: 70%; filter: blur(64px); background-color: #000; position: absolute; }
JavaScript
const iphone = document.querySelector('.iphone-holder'); const backgroundText = document.querySelector('.hero-text-holder'); const heroTextBlur = document.querySelectorAll('.hero-text-blur'); // 存储当前偏移值,用于缓动计算 let currentIphoneX = 0; let currentTextX = 0; let currentBlurX = 0; // 缓动系数,值越小过渡越平滑 const easeFactor = 0.15; function updateParallax(e) { const halfWindow = window.innerWidth / 2; const xVal = e.clientX - halfWindow; const positionInWindow = xVal / window.innerWidth; // 计算各元素的目标偏移值 const targetIphoneX = 10 * positionInWindow; const targetTextX = -0.3 * 10 * positionInWindow; const targetBlurX = -2 * 10 * positionInWindow; // 缓动更新当前偏移值 currentIphoneX += (targetIphoneX - currentIphoneX) * easeFactor; currentTextX += (targetTextX - currentTextX) * easeFactor; currentBlurX += (targetBlurX - currentBlurX) * easeFactor; // 应用变换到元素 iphone.style.transform = `translateX(${currentIphoneX}%)`; backgroundText.style.transform = `translateX(${currentTextX}%)`; heroTextBlur.forEach(el => { el.style.transform = `translateX(${currentBlurX}%)`; }); } // 监听全局鼠标移动事件 document.addEventListener('mousemove', updateParallax); // 鼠标离开页面时重置元素位置 document.addEventListener('mouseleave', () => { currentIphoneX = 0; currentTextX = 0; currentBlurX = 0; iphone.style.transform = `translateX(0)`; backgroundText.style.transform = `translateX(0)`; heroTextBlur.forEach(el => { el.style.transform = `translateX(0)`; }); });
内容的提问来源于stack exchange,提问作者The Old County
相关产品推荐
相关产品推荐

