【问题标题】:Change duration of canvas animation with Request Animation Frame使用请求动画帧更改画布动画的持续时间
【发布时间】:2016-08-29 13:22:53
【问题描述】:

我正在尝试制作一个类似于进度条的圆形动画。我打算在轮播中使用它来跟踪下一张幻灯片何时出现。我遇到的问题是我不知道如何更改动画的持续时间。我尝试调整帧速率,它可以工作,但动画变得非常不稳定。 setInterval 有点工作,但它显示整个圆圈,而不是像我想要的那样显示它的一部分,所以我无法正确计时。我需要能够控制动画的速度,在不卡顿的情况下放慢速度。我正在处理的代码如下。

<script>    
    (function() {
        var requestAnimationFrame = window.requestAnimationFrame || 
                                    window.mozRequestAnimationFrame ||
                                    window.webkitRequestAnimationFrame || 
                                    window.msRequestAnimationFrame;
                                    window.requestAnimationFrame = requestAnimationFrame;
    })();
        var canvas = document.getElementById('myCanvas');
        var context = canvas.getContext('2d');
        var centerX = canvas.width / 2;
        var centerY = canvas.height / 2;
        var radius = 90;
        var endPercent = 85;
        var curPerc = 0;
        var circ = -Math.PI;
        var quart = -(Math.PI * 2) + 1;

        function animate(current) {
            context.clearRect(0, 0, canvas.width, canvas.height);
            context.beginPath();
            context.arc(centerX, centerY, radius, -(quart), ((circ) * current) - quart, true);
            context.lineWidth = 3;
            context.strokeStyle = '#000';
            context.stroke();
            curPerc++;
            if (curPerc < endPercent) {
                requestAnimationFrame(function () {
                animate(curPerc / 100)
                });
            }
        }

     animate();
</script>

【问题讨论】:

标签: animation canvas requestanimationframe


【解决方案1】:

requestAnimationFrame 确实在回调参数中传递了一个高分辨率时间戳。所以你可以使用它来确定你在当前动画中的位置,并使用这个增量时间来设置你的位置变量而不是curPerc++

这是一个幼稚的实现。

var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 90;
var endPercent = 85;
var quart = -(Math.PI * 2) + 1;
var startTime = null;
var duration = null;

function animate(time) {

  if (!startTime) {
    startTime = time;
  }

  var delta = Math.min(1, (time - startTime) / duration);
  var curPerc = ((-2 * Math.PI) / 100) * (endPercent * delta);

  context.clearRect(0, 0, canvas.width, canvas.height);
  context.beginPath();
  context.arc(centerX, centerY, radius, -quart, curPerc - quart, true);
  context.stroke();

  if (delta < 1) {
    requestAnimationFrame(animate);
  } else {
    startTime = null;
    slider.disabled = false;
  }
}

var startAnim = function() {
  context.lineWidth = 3;
  context.strokeStyle = '#000';

  slider.disabled = true;
  duration = +slider.value;
  l.textContent = duration + 'ms';
  requestAnimationFrame(animate);
};
slider.onchange = startAnim;
startAnim();
<p>use the slider to update the animation's duration</p>
<input type="range" min="250" max="9000" value="2000"id="slider" />
<label id="l"></label><br>
<canvas id="myCanvas" height="300"></canvas>

【讨论】:

  • @markE,您的编辑是正确的。通常我什至在if(delta&gt;=1) 中添加一个“绘制最后一帧”调用,我确实将它放在我的动画函数之上。只是懒得在这里用 OP 的结构正确地做到这一点。
  • 非常感谢。我搜索了很多东西,找不到正确的答案。
猜你喜欢
  • 1970-01-01
  • 2018-06-15
  • 2013-01-18
  • 2013-05-09
  • 1970-01-01
  • 2014-05-16
  • 1970-01-01
  • 2021-01-18
  • 1970-01-01
相关资源
最近更新 更多