2

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

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

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

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

编辑:我试图弄清楚使用 context.translate。但是每秒的每个间隔(假设 setInterval 的毫秒为 1000),它都会使值加倍。

4

1 回答 1

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 offsetX=0;
    var offsetY=0;
    var rectX=0;
    var rectY=0;

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

顺便说一句,Loktar 是完全正确的,除了快速测试之外,您还需要使用 requestAnimationFrame 而不是 setInterval。requestAnimation 框架已内置优化,可提高性能并减少资源使用。

    // 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 之后,缓存的图像将与画布的顶部/左侧完全对齐。然后,您只需将缓存的网格移动到画布左侧和顶部的起始位置。然后重复动画!非常快,非常流畅。

于 2013-03-28T22:02:37.483 回答