为HTML5循环网格?

时间:2013-03-28 20:41:00

标签: javascript html5 canvas

我为我的背景制作了一个网格。我能够在X和Y上使用for循环制作一个网格来绘制正方形。

有没有办法让网格动画在两个轴上使用+ = 1在x和y上移动?

我正在考虑将网格划分为一个大图层并为图层设置动画,而不是为每个正方形设置动画。

http://jsbin.com/emexaz/1/edit

编辑:我正在尝试使用context.translate。但是每秒的每个间隔(假设setInterval的毫秒为1000),它会使值翻倍。

1 个答案:

答案 0 :(得分:2)

以下是如何在画布中循环网格

绘制移动网格有多种方法。这是其中之一。

这是代码和小提琴:http://jsfiddle.net/m1erickson/AjZhD/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
</style>

<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");

    var w=canvas.width;
    var h=canvas.height;
    var offsetX=0;
    var offsetY=0;
    var rectX=0;
    var rectY=0;

    setInterval(function(){drawGrid();},100);

    function drawGrid(){

      // move the grid
      offsetX+=5;
      offsetY+=5;
      if(offsetX==20){offsetX=0;}
      if(offsetY==20){offsetY=0;}
      rectX+=5;
      rectY+=5;
      if(rectX==w){rectX=0;}
      if(rectY==h){rectY=0;}

      ctx.save();
      ctx.clearRect(0,0, w, h);
      ctx.strokeStyle="gray";
      ctx.beginPath();
      // vertical grid lines
      for(var x=offsetX;x<w;x+=20){
            ctx.moveTo(x,0);
            ctx.lineTo(x,h);    
      }
      // horizontal grid lines
      for(var y=offsetY;y<h;y+=20){
            ctx.moveTo(0,y);
            ctx.lineTo(w,y);    
      }
      // "moving" rect
      ctx.fillStyle="red";
      ctx.rect(rectX-4,rectY-4,8,8);

      ctx.stroke();
      ctx.fill();
      ctx.restore();

  }

}); // end $(function(){});
</script>

</head>

<body>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

[编辑有关代码如何工作的详细信息]

可以......这里有更详细的解释。

这些var将让我们在画布上向右移动网格线。它们告诉我们在哪里绘制网格的下一帧和下一个红色矩形:

    var offsetX=0;
    var offsetY=0;
    var rectX=0;
    var rectY=0;

然后setInterval是一个每100毫秒调用一次drawGrid()的循环。

BTW,Loktar完全正确,除了快速测试之外,你还需要使用requestAnimationFrame而不是setInterval。 requestAnimation frame内置了优化功能,可以提高性能并减少资源使用。

    // repease drawGrid() every 100 milliseconds
    setInterval(function(){drawGrid();},100);

在drawGrid()中,我们增加offsetX / Y和rectX / Y,这使我们开始向右和向下绘制网格。请注意,移动20px后,网格基本上回到了相同的视觉位置,就像我们开始时一样!这允许我们简单地将我们的移动偏移重置为0并创建视觉错觉,即网格向右/向下行进超过1平方。然而,rectX / Y确实在网格上向右/向下继续(增加了运动的错觉)。

      // move the grid
      offsetX+=5;
      offsetY+=5;
      if(offsetX==20){offsetX=0;}
      if(offsetY==20){offsetY=0;}
      rectX+=5;
      rectY+=5;
      if(rectX==w){rectX=0;}
      if(rectY==h){rectY=0;}

最后我们只绘制网格。首先我们绘制垂直线直到我们到达画布的末尾。然后是水平线。最后我们绘制了一个红色矩形,它创建了一个视觉错觉,网格向右/向下移动了超过1个网格。

      for(var x=offsetX;x<w;x+=20){
            ctx.moveTo(x,0);
            ctx.lineTo(x,h);    
      }
      // horizontal grid lines
      for(var y=offsetY;y<h;y+=20){
            ctx.moveTo(0,y);
            ctx.lineTo(w,y);    
      }
      // "moving" rect
      ctx.fillStyle="red";
      ctx.rect(rectX-4,rectY-4,8,8);

根据您想要的移动网格,有一些方法可以使网格更快更顺畅地飞行。 Loktar描述了使用requestAnimationFrame,它比setInterval做得更好。如果您想要非常快速和平滑,您可以简单地保存完整网格的图像并移动该图像,而不是重绘所有网格线。保存图像以便重用称为缓存。

如果您缓存的网格比画布宽1平方,高1平方,则可以重复使用视觉错误。你可以开始动画,超大的网格比画布更靠左,更远。然后使用每个动画帧,您将向右/向下移动网格1px。在20px之后,缓存的图像将与画布的顶部/左侧精确对齐。然后,您只需将缓存的网格移动到它的左侧和画布顶部的起始位置。然后重复动画!非常快,非常顺利。