如何停止画布跳跃动画

时间:2018-04-25 12:33:50

标签: javascript canvas html5-canvas

我有一个画布动画,你可以看到here

我注意到,一旦你观看了一段时间后的动画(约25秒),动画就会开始跳转。我正在努力弄清楚如何使它成为一个恒定的流体运动?

以下代码:

<canvas id="canvas"></canvas>

var canvas = document.querySelector("#canvas");
var ctx = canvas.getContext("2d");
canvas.width = parseInt(getComputedStyle(canvas).width);
canvas.height = parseInt(getComputedStyle(canvas).height);

var P = 4;
var A = 4;

function draw(shift) {
   var w = canvas.width;
   var h = canvas.height;
   shift = shift >= 500*Math.PI ? shift - 100*Math.PI : shift;
   ctx.clearRect(0, 0, w, h);
   var grd = ctx.createLinearGradient(0, 0, w, h);
   grd.addColorStop(0, "#4a8bf5");
   grd.addColorStop(1, "#f16b55");
   ctx.strokeStyle = grd;

   ctx.lineCap = "round";
   for (var i = 0; i < w; ) {
      var _A = Math.abs(A*Math.cos(2*i));
      ctx.beginPath();
      var pos = Math.exp(-_A * i / w) * Math.sin(P * Math.PI * (i + shift) / w);
      pos *= h / 2;
      var lw = Math.exp(-_A * i / w) * Math.sin(3 * Math.PI * (i - shift) / w) * 2;
      ctx.lineWidth = (lw)+1;
      ctx.lineTo(i, h / 2 - pos);
      ctx.closePath();
      ctx.stroke();
      i += 1;
   }

   window.requestAnimationFrame(function(){
      draw(shift + 1);
   });
}
draw(0);

1 个答案:

答案 0 :(得分:0)

解决方案是确保移位的变化导致sin()参数改变2π的倍数。

鉴于

Math.sin((i + shift) / (w / P))

这可以使用

之类的东西来完成
if (shift > 500) shift -= 2 * Math.PI * (w / P);

这里的第二个sin()参数仍然会跳转,即线宽。为了避免这种情况,shift必须减少一个数字,使得两个参数都以2π的倍数变化,如果你愿意,可以改变LCM。

var canvas = document.querySelector("#canvas");
var ctx = canvas.getContext("2d");
canvas.width = parseInt(getComputedStyle(canvas).width);
canvas.height = parseInt(getComputedStyle(canvas).height);

var P = 10;
var A = 4;

var shift = 0;

function draw() {
  var w = canvas.width;
  var h = canvas.height;
  shift += 1;
  if (shift > 500) shift -= 2 * Math.PI * (w / P);
  shift_el.innerHTML = shift;
  ctx.clearRect(0, 0, w, h);
  var grd = ctx.createLinearGradient(0, 0, w, h);
  grd.addColorStop(0, "#4a8bf5");
  grd.addColorStop(1, "#f16b55");
  ctx.strokeStyle = grd;

  ctx.lineCap = "round";
  for (var i = 0; i < w;) {
    var _A = Math.abs(A * Math.cos(2 * i));
    ctx.beginPath();
    var pos = Math.exp(-_A * i / w) * Math.sin((i + shift) / (w / P));
    pos *= h / 2;
    var lw = Math.exp(-_A * i / w) * Math.sin(3 * Math.PI * (i - shift) / w) * 2;
    ctx.lineWidth = (lw) + 1;
    ctx.lineTo(i, h / 2 - pos);
    ctx.closePath();
    ctx.stroke();
    i += 1;
  }
  window.requestAnimationFrame(draw);
}
draw();
body {
  background: #ffffff;
  padding: 0;
  margin: 0;
}

canvas {
  height: 200px;
  width: 100%;
}

#shift_el {
  position: absolute;
  top: 0
}
<canvas id="canvas"></canvas>
<div id="shift_el"></div>