首页 > 解决方案 > Javascript动画倒计时

问题描述

我一直在尝试创建一个倒计时,每次计数器更改时都会为​​文本设置动画。我可以在开始时执行更改,但不知道如何清除更改并重复它。

HTML 和 CSS

<!DOCTYPE html>
<html>
<head>
    <!--meta http-equiv="refresh" content="4; url=index.php"-->
    <style type="text/css">
        p
        {
            transition: 1s;
            font-size: 100%;
        }
    </style>
</head>
<body>

<p>A script on this page starts this clock:</p>
<p id="demo">Login in....</p>

<script>

    //various javascript here

</script>
</body>
</html>

此脚本在第一次计数时更改 CSS 一次,但在计数 2 或 1 时不更改。

//Set the counter variable
    var counter= 4;

    //Set the timer to count the counter down
    var timer = setInterval(function() 
    {
        counter--;
        if(counter== 0) 
        {
            clearInterval(timer);
        } 
        else 
        {
            //Execute the CSS change function
            styleChange();
        }
    }, 1000);

    function styleChange()
    {
        document.getElementById("demo").innerHTML = (counter);
        document.getElementById("demo").style.fontSize = "500%";
        document.getElementById("demo").style.opacity = "0";
        // In CSS "Demo" is given a transition of 1s to smooth out the animation"
    }

下一个脚本不会在每次计数器时重置样式,而是在样式之间切换,这不是我想要做的,但至少它与第一个脚本不同。它只会影响样式,如果它有效,我会添加计时器。

    var myVar = setInterval(setStyle, 1000);

    function setStyle() {
      var x = document.getElementById("demo");
      x.style.fontSize = x.style.fontSize == "100%" ? "500%" : "100%";
    }

    function stopStyle() {
      clearInterval(myVar);
    }

我想尝试使用“for”循环遍历计数器的值,更改值更改的样式,然后重置值,但我无法让它工作。从视觉上看,效果应该是这样的,但是是反向播放的,而不是在 acid-> https://www.youtube.com/watch?v=hsUKu9_Lr6U上播放。我从 w3schools 页面中大量借鉴了关于 setInterval 和 clearInterval 的内容。

标签: javascriptcssanimationsetintervalcountdown

解决方案


您不需要两个单独的间隔来使文本变大和变小。

相反,您可以使用 CSS 过渡来设置font-size从小到大的动画,并使用 2 个嵌套的 Window.requestAnimationFrame()调用来正确计时,如下所示:

const counter = document.getElementById('counter');
let value = 11;

const intervalID = setInterval(() => {
  const nextValue = --value;
  
  if (nextValue === -1) {
    clearInterval(intervalID);
    
    return;
  }
  
  requestAnimationFrame(() => {
    // Update the value and remove the `big` class in the next frame, so that
    // the text becomes smaller again:
    counter.textContent = nextValue;
    counter.classList.remove('big');
  
    requestAnimationFrame(() => {
      // One more frame after that (so that the element has time to be re-rendered
      // with the smaller font-size, add the `big` class again:
      counter.classList.add('big');
    });
  });
  
}, 1000);
body {
  margin: 0;
  display: flex;
  height: 100vh;
  justify-content: center;
  align-items: center;
  font-family: monospace;
}

#counter.big {
  font-size: 500%;
  opacity: 0;
  transition: all linear 1s;
}
<div id="counter" class="big">10</div>

您甚至可以使用CSS 自定义属性轻松更改间隔延迟,同时使其与 CSS 保持同步transition-duration

const duration = 0.5; // In seconds
const counter = document.getElementById('counter');
let value = 11;

counter.style.setProperty('--transition-duration', `${ duration }s`);

const intervalID = setInterval(() => {
  const nextValue = --value;
  
  if (nextValue === -1) {
    clearInterval(intervalID);
    
    return;
  }
  
  requestAnimationFrame(() => {
    // Update the value and remove the `big` class in the next frame, so that
    // the text becomes smaller again:
    counter.textContent = nextValue;
    counter.classList.remove('big');
  
    requestAnimationFrame(() => {
      // One more frame after that (so that the element has time to be re-rendered
      // with the smaller font-size, add the `big` class again:
      counter.classList.add('big');
    });
  });
  
}, duration * 1000);
body {
  margin: 0;
  display: flex;
  height: 100vh;
  justify-content: center;
  align-items: center;
  font-family: monospace;
}

#counter.big {
  /* Default value: */
  --transition-duration: 1s;
  
  font-size: 500%;
  opacity: 0;
  transition: all linear var(--transition-duration);
}
<div id="counter" class="big"></div>


推荐阅读