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

滚动动画适配不同页面高度:如何按视口范围精准触发?

问题场景

滚动动画在测试页面可正常运行,但在最终页面中因页面高度不同,动画触发时机远早于预期。需求是让动画在目标元素从视口100%可见滚动到0%可见的过程中触发,适配任意页面高度。

原代码如下:

原JS代码

var scroll = document.querySelector ('.curve');
window.addEventListener ('scroll', function(){
    var value =  1 + window.scrollY / -200;
    scroll.style.transform = `scaleY(${value})`;
})

原CSS代码

* {
  margin:0;
  padding:0;
}
body {
  height:200vh;
  background-color:#111; 
}
section {
  position:absolute;
  width:100%;
  height:100%;
  background:#ff2;  
}
section .curve {
  position:absolute;
  bottom:-200px;
  height:200px;
  width:100%;
  transform-origin:top;
}
section .curve img{
    width:100%;
    height:100%;  
}

原HTML代码

<body>
  <section>
    <span class="curve">
      <img src="https://wordpress-899937-3173615.cloudwaysapps.com/wp-content/uploads/2023/01/curve-white-300x59.png">
    </span>
  </section>
</body>
解决方案

核心思路是基于元素在视口中的可见比例计算动画参数,而非依赖固定的滚动距离数值,这样就能适配任意页面高度。

修改后的JS代码如下:

const curveEl = document.querySelector('.curve');
const curveHeight = curveEl.offsetHeight;

window.addEventListener('scroll', () => {
  // 获取元素相对于视口的位置信息
  const rect = curveEl.getBoundingClientRect();
  // 计算元素在视口中的可见高度:顶部在视口内取顶部到底部,否则取视口底部到元素顶部的距离,最小为0
  const visibleHeight = Math.max(0, Math.min(curveHeight, window.innerHeight - rect.top));
  // 计算可见比例,范围0-1
  const visibleRatio = visibleHeight / curveHeight;
  // 将比例作为scaleY的值,实现从1到0的平滑过渡
  curveEl.style.transform = `scaleY(${visibleRatio})`;
});

代码说明

  1. 预取元素高度:提前获取.curve元素的高度,避免每次滚动都重新计算,优化性能
  2. 实时计算可见区域:利用getBoundingClientRect()获取元素在视口中的实时位置,计算当前可见高度
  3. 推导可见比例:用可见高度除以元素总高度,得到0-1之间的比例值
  4. 应用动画变换:将比例值作为scaleY参数,元素完全在视口中时比例为1(无缩放),完全滚出时比例为0(完全收缩),精准匹配需求的触发时机

性能优化补充

可添加requestAnimationFrame减少滚动事件的触发频率,提升流畅度:

const curveEl = document.querySelector('.curve');
const curveHeight = curveEl.offsetHeight;
let ticking = false;

function updateAnimation() {
  const rect = curveEl.getBoundingClientRect();
  const visibleHeight = Math.max(0, Math.min(curveHeight, window.innerHeight - rect.top));
  const visibleRatio = visibleHeight / curveHeight;
  curveEl.style.transform = `scaleY(${visibleRatio})`;
  ticking = false;
}

window.addEventListener('scroll', () => {
  if (!ticking) {
    requestAnimationFrame(updateAnimation);
    ticking = true;
  }
});

内容的提问来源于stack exchange,提问作者Lisandro Cejas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 22:05:22