You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于JavaScript实现仅X轴方向的视差元素效果

X轴鼠标视差效果实现方案

核心问题解答

1. 鼠标移动事件监听对象

  • 优先监听document:只要鼠标在页面内移动就触发视差效果,避免鼠标移出目标区域后效果中断,适配全局视差场景。
  • 仅需特定区域生效时:监听.hero-section元素,仅当鼠标处于该区域内时触发视差。

2. 元素位置计算公式

核心逻辑是将鼠标位置转换为相对视口中心的偏移比例,再乘以自定义视差强度,实现不同层级元素的差异化移动:

  1. 计算鼠标相对于视口中心的X轴偏移量:
    const mouseXOffset = e.clientX - window.innerWidth / 2;
    
  2. 将偏移量转换为正负比例值(表示左右方向):
    const offsetRatio = mouseXOffset / window.innerWidth;
    
  3. 为不同层级元素设置差异化视差强度,计算最终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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 05:40:56