javascript - 通过纯js​​创建动画彩虹

标签 javascript html5-canvas

代码(纯 js)用于创建动画彩虹,其中连续的彩虹会延迟一点时间。但动画不一致(最终减慢)。我只是编程的初学者,所以我的代码也越来越长。

如果你在本地运行代码,动画会在一段时间后变慢,并且彩虹出现的方式不一致(每条彩虹之间应该有时间间隔)。我的第二个问题是我想减少代码,这样我就不必为每个彩虹动画创建一个函数。

function anim()
{
  var x,y,z,p,q,r;
  x = y = z = p = q = r  = 2*Math.PI;
  var c = document.getElementById("myCanvas");
  var ctx = c.getContext("2d");
  ctx.clearRect(0,0,c.width,c.height);

  var id = setInterval(frame_one,1);
  var t = setInterval(frame_two,1);
  var u = setInterval(frame_three,1);
  var v = setInterval(frame_four,1);
  var w = setInterval(frame_five,1);
  var s = setInterval(frame_six,1);
  function frame_one()
  {
    if (x <=(Math.PI)) 
    {
      clearInterval(id);
      x = 2*Math.PI;
    }
    else
    {
      x = x - 0.036;
      ctx.lineWidth = 20;			
      ctx.beginPath();
      ctx.arc(c.width/2, c.height/2, c.height/2-20, 2* Math.PI,x,true);
      ctx.strokeStyle="red";
      ctx.stroke();			
    }		
  }		
  function frame_two()
  {
    if (y <= (Math.PI)) 
    {
      y  = 2*Math.PI;
      clearInterval(t);
    }
    else 
    {
      y= y - 0.032; 		
      ctx.beginPath();
      ctx.lineWidth=20;
      ctx.arc(c.width/2,c.height/2, c.height/2-40, 2* Math.PI,y,true);
      ctx.strokeStyle="orange";
      ctx.stroke();		
    }
  }		
  function frame_three()
  {
    if (z <= (Math.PI)) 
    {
      clearInterval(u);
    }
  else 
    {
      z = z - 0.028; 		
      ctx.beginPath();
      ctx.lineWidth = 20;
      ctx.arc(c.width/2,c.height/2,(c.height)/2-60, 2* Math.PI,z,true);
      ctx.strokeStyle = "yellow";
      ctx.stroke();
    }
  }		
  function frame_four()
  {
    if (p <= (Math.PI)) 
    {
        clearInterval(v);
    }
    else 
    {
      p = p - 0.024; 		
      ctx.beginPath();
      ctx.lineWidth = 20;
      ctx.arc(c.width/2,c.height/2,(c.height)/2-80, 2* Math.PI,p,true);
      ctx.strokeStyle = "green";
      ctx.stroke();
    }
  }		
  function frame_five()
  {
    if (q <= (Math.PI)) 
    {
      clearInterval(w);
    }
    else 
    {
      q = q - 0.020; 		
      ctx.beginPath();
      ctx.lineWidth = 20;
      ctx.arc(c.width/2,c.height/2,(c.height)/2-100, 2* Math.PI,q,true);
      ctx.strokeStyle = "blue";
      ctx.stroke();
    }
  }		
  function frame_six()
  {
    if (r <= (Math.PI)) 
    {
      clearInterval(s);
    }
    else 
    {
      r = r - 0.016; 		
      ctx.beginPath();
      ctx.lineWidth = 20;
      ctx.arc(c.width/2,c.height/2,(c.height)/2-120, 2* Math.PI,r,true);
      ctx.strokeStyle = "violet";
      ctx.stroke();
    }
  }									
}
anim();
setInterval(anim,3000);
<canvas onclick="info()" id="myCanvas" width="500" height="500" style="border:1px solid #d3d3d3;"></canvas>

最佳答案

这只是几种方法中的一种。内圈似乎动画速度较慢的原因之一是由于它的大小:因为它较小,所以它会在同一时间段内以较小的步长移动。您可以通过减少其持续时间来对此进行补偿。

示例代码

使用描边结合线宽而不是填充允许我们使用诸如“圆形”(如下所示)之类的帽类型,但它也简化了所需的计算。

当然,我建议清除每一帧以移除重叠的抗锯齿像素,这会形成硬边。

var ctx = c.getContext("2d"),
   /* All these settings are dynamic so one can alter number of colors,
      sizes, line width etc. without modifying the code */
    colors = ["red", "orange", "yellow", "green", "blue", "violet"],
    radius = 140,    // max radius
    lineWidth = 16,  // width of each arc in pixels
    delay = 300,     // ms
    duration = 1000, // ms (per arc)
    startTime;       // for animation loop

// initialize common line width and cap
ctx.lineWidth = lineWidth;
ctx.lineCap = "round";

// helper: draw arc from start to end angle at given color and position
// arc(): https://devdocs.io/dom/canvasrenderingcontext2d/arc
function arc(radius, angle, color) {
  ctx.beginPath();  // clear existing path and sub-paths
  ctx.arc(c.width*0.5, c.height, radius, angle, Math.PI*2); // end-angle always 360°
  ctx.strokeStyle = color;
  ctx.stroke();     // render arc
}

function draw(time) {
  if (!startTime) startTime = time;     // initialize start time if none is initialized
  ctx.clearRect(0,0,c.width,c.height);  // clear canvas per frame

  // iterate over color-array, then for each color entry:
  colors.forEach(function(color, i) {
  
    /* Calc t to a normalized value. We're interested in the values primarily
       between [0, 1]. To offset the delay we can use the current index times
       delay. We subtract it from current time so get a delay.
       startTime is the subtracted from this so we are relative to the beginning
       of the animation.
       And finally divide on duration to normalize.
    */
    var t = ((time - i * delay) - startTime) / duration;
    
    /* t may be lower than 0; we're only interested in t when it is equal or
       more than 0. We don't care about it being above 1 since we will clamp
       the angle below and we need to redraw each arc per frame */
    if (t >= 0) {
    
      /* arc(radius, startAngle, color) 
         Here we calculate radius from max minus linewidth times index of color.
         For start angle we start at 360° (in radians which is 2xPI).
         Then we use normalized t to get a value of 180° (or PI in radians).
         We subtract this from 360 so we go from [360°, 180°], e.g. drawing
         an arc from right side to left going in an arc over the canvas (not under).
         And finally we pass in the current color
      */
      arc(radius - lineWidth * i, Math.max(Math.PI, Math.PI * 2 - Math.PI * t), color);
    }
  });
  
  /* Animate until all are drawn. We calculate max time using duration + each delay
     times the number of colors */
  if (time < startTime + colors.length * delay + duration) requestAnimationFrame(draw);
}

// invoke animation passing a time argument
requestAnimationFrame(draw);
<canvas id=c></canvas>

关于javascript - 通过纯js​​创建动画彩虹,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45751748/

相关文章:

html5-canvas - 为什么我不能在我的 HTML5 Canvas 中绘制两条不同颜色的线?

javascript - 更改日期时间选择器语言不起作用

javascript - 如何使用 .each() 分隔内容 - jQuery

javascript - 让 UploadFS 与 angular2-meteor 一起工作

javascript - 来自 .create 和序列化表单的 Backbone.js 事件

javascript - toDataURL 抛出未捕获的安全异常

javascript - Bootstrap css 定制和 javascript 未加载(Ruby 1.9.3p547,Rails 4.1.4)

javascript - 如何从javascript函数中获取值?

javascript - 三.js 中 Canvas 上的 IP 摄像机流

javascript - 使用图案填充时 canvas.toblob 失败