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

滚动时同步触发两个动画的技术问题求助

Fixing Sync Issues Between Scroll-Triggered Animations

Hey there! Let's sort out this animation sync problem you're facing. The core issue here is likely that your two animations aren't being triggered at the exact same moment, or their timing/duration settings are misaligned—leading to one finishing before the other even though you set a 2s duration for the line.

Here's what to do to get them in lockstep:

  • Use a single trigger to activate both animations
    Instead of handling the box and line separately, tie both animations to a single CSS class that you add/remove via your scroll listener. This guarantees they start and stop at the exact same time.

  • Match animation durations and timing functions
    If your line's animation runs for 2s, make sure the box's movement also uses the same duration and easing curve. Even a tiny difference in timing will make them feel out of sync.

  • Refine your scroll trigger calculation
    Double-check that your trigger point is calculated correctly—if it's firing too early (or late) due to incorrect offset/height math, that can make it seem like animations are finishing prematurely.

Working Code Example

HTML

<div id="section-one">
  <div class="box">
    <div class="line"></div>
  </div>
</div>

CSS

.box {
  position: relative;
  left: 0;
  /* Match the line's animation duration and easing */
  transition: left 2s ease; 
}

/* This class triggers both animations */
.box.active {
  left: 100px;
}

.line {
  width: 0;
  height: 3px;
  background-color: #222;
  /* Sync duration with the box */
  transition: width 2s ease; 
}

.box.active .line {
  width: 100px;
}

JavaScript

const sectionOne = document.getElementById('section-one');
const box = document.querySelector('.box');

// Add a debounce to avoid excessive scroll event firing (optional but recommended)
function debounce(func, delay = 100) {
  let timeoutId;
  return (...args) => {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => func.apply(this, args), delay);
  };
}

const handleScroll = debounce(() => {
  const sectionHeight = sectionOne.offsetHeight;
  const sectionTop = sectionOne.offsetTop;
  // Calculate the exact trigger point: 1/3 of the section's height from the top
  const triggerThreshold = sectionTop + sectionHeight / 3;
  // Current scroll position (accounting for viewport height)
  const currentScroll = window.scrollY + window.innerHeight;

  if (currentScroll > triggerThreshold) {
    box.classList.add('active');
  } else {
    // Optional: Reset animations when scrolling back above the threshold
    box.classList.remove('active');
  }
});

window.addEventListener('scroll', handleScroll);

Why This Works:

  • By using the active class on the parent .box element, both the box's position change and the line's width expansion are triggered simultaneously.
  • Matching the transition duration and easing for both elements ensures they start and finish at the exact same time.
  • The debounced scroll handler prevents the animation from being triggered hundreds of times per second, which can cause unexpected behavior like premature completion.

内容的提问来源于stack exchange,提问作者Marius Gardelli

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:09:08