Javascript 相交观察者:具有相同类的多个元素,仅在可见元素上运行动画

Javascript 相交观察者:具有相同类的多个元素,仅在可见元素上运行动画,javascript,animation,intersection-observer,Javascript,Animation,Intersection Observer,我有以下代码,这是一个动画计数器 它包含具有相同类的多个元素 我希望计数器动画仅在每个元素进入视口时运行;并且仅在刚进入视口的元素上 换句话说,当用户向下滚动页面时,数字进入视口时会产生动画效果 此时,只要第一个元素进入视口,动画就会在具有相同类的所有元素上运行 解决这个问题的办法是什么 <html> <body> <span class="countup">1000</span> <div style="he

我有以下代码,这是一个动画计数器

它包含具有相同类的多个元素

我希望计数器动画仅在每个元素进入视口时运行;并且仅在刚进入视口的元素上

换句话说,当用户向下滚动页面时,数字进入视口时会产生动画效果

此时,只要第一个元素进入视口,动画就会在具有相同类的所有元素上运行

解决这个问题的办法是什么

<html>
<body>

<span class="countup">1000</span>
<div style="height: 400px"></div>
<span class="countup">2000</span>
<div style="height: 400px"></div>
<span class="countup">3000</span>

</body>
<script>
// How long you want the animation to take, in ms
const animationDuration = 2000;
// Calculate how long each ‘frame’ should last if we want to update the animation 60 times per second
const frameDuration = 1000 / 60;
// Use that to calculate how many frames we need to complete the animation
const totalFrames = Math.round( animationDuration / frameDuration );
// An ease-out function that slows the count as it progresses
const easeOutQuad = t => t * ( 2 - t );

// The animation function, which takes an Element
const animateCountUp = el => {
    let frame = 0;
    const countTo = parseInt( el.innerHTML, 10 );
    // Start the animation running 60 times per second
    const counter = setInterval( () => {
        frame++;
        // Calculate our progress as a value between 0 and 1
        // Pass that value to our easing function to get our
        // progress on a curve
        const progress = easeOutQuad( frame / totalFrames );
        // Use the progress value to calculate the current count
        const currentCount = Math.round( countTo * progress );

        // If the current count has changed, update the element
        if ( parseInt( el.innerHTML, 10 ) !== currentCount ) {
            el.innerHTML = currentCount;
        }

        // If we’ve reached our last frame, stop the animation
        if ( frame === totalFrames ) {
            clearInterval( counter );
        }
    }, frameDuration );
};

// Run the animation on all elements with a class of ‘countup’
const runAnimations = () => {
    const countupEls = document.querySelectorAll( '.countup' );
    countupEls.forEach( animateCountUp );
};


// Intersection Observer: 

const onIntersection = (entries) => {
    for (const entry of entries) {
      if (entry.isIntersecting) {
        console.log(entry);
        runAnimations();
      }
    }
  };
  
  const observer = new IntersectionObserver(onIntersection);
  observer.observe(document.querySelector('.countup'));
</script>
</html>

1000
2000
3000
//希望动画持续多长时间,以毫秒为单位
const animationDuration=2000;
//如果要每秒更新动画60次,请计算每个“帧”应持续多长时间
const frameDuration=1000/60;
//使用它来计算完成动画需要多少帧
const totalFrames=Math.round(animationDuration/frameDuration);
//一种缓解功能,可在计数过程中降低计数速度
常数easeOutQuad=t=>t*(2-t);
//动画函数,它接受一个元素
常量animateCountUp=el=>{
设frame=0;
const countTo=parseInt(el.innerHTML,10);
//启动动画,每秒运行60次
常量计数器=设置间隔(()=>{
frame++;
//将进度计算为0到1之间的值
//将该值传递给我们的缓和函数,以获得
//曲线上的进展
const progress=easeOutQuad(帧/总帧);
//使用进度值计算当前计数
const currentCount=数学轮(countTo*进度);
//如果当前计数已更改,请更新元素
if(parseInt(el.innerHTML,10)!==currentCount){
el.innerHTML=当前计数;
}
//如果已到达最后一帧,请停止动画
如果(帧===总帧){
清除间隔(计数器);
}
},帧时长);
};
//使用“倒计时”类在所有元素上运行动画
常量runAnimations=()=>{
const countupEls=document.queryselectoral('.countup');
countupEls.forEach(animatecocountup);
};
//交叉口观察员:
常量onIntersection=(条目)=>{
for(条目的常量输入){
if(输入。isIntersecting){
控制台日志(条目);
运行动画();
}
}
};
const observer=新的IntersectionObserver(onIntersection);
observer.observe(document.querySelector('.countup'));
感谢向上计数动画