JS Canvas单独为网格元素设置动画

时间:2015-02-08 04:11:49

标签: javascript html5 canvas particles

我通过使用for循环生成六边形网格,我有一些问题

    for (var i=0; i <= rows; i++) {
        for (var j=0; j <= cols; j++) {
            ctx.save();
            ctx.translate(0+i*distX, 0+j*distY);
            drawHexagon(ctx);
            ctx.fill();
            ctx.restore();
        }
    }

我的最终目标是创建一个六边形网格,当它在页面上移动时会移动远离鼠标光标的影响区域。我无法弄清楚如何在每个六边形之间绘制一条路径,而且我在尝试为六边形设置动画时遇到了问题。

我还是画布新手,我浏览了Mozilla开发者网络上的教程,所有动画都是在单个对象上,而不是在网格中生成的对象。

我在想我应该尝试存储网格并稍后影响它,但我不确定如何去做,我也不认为画布是这样的。

我发现这几乎是我想做的事情,但我无法理解它是如何工作的: http://codepen.io/soulwire/pen/Ffvlo

我现在很好地梳理它,如果有人能指引我通过它会很棒:)

编辑:我已经在点后面画了一个网格,我也想操纵它。我仍然不理解上面链接的编码器,它有点过头了。

1 个答案:

答案 0 :(得分:4)

您的链接适用2种力量:

  1. 鼠标附近的粒子被击退。更具体地说,如果粒子中心点靠近鼠标中心点,那么粒子就会沿着两个中心点之间的线排斥。

  2. 不靠近鼠标的粒子被吸引回到原来的位置。更具体地说,粒子沿其当前中心点与其原始中心点之间的线移向其原始中心点。

  3. 数学运算如下:

    // Given the mouse centerpoint (mx,my) & particle's centerpoint (px,py)
    
    // calculate the difference between x's & y's
    var dx=px-mx;
    var dy=py-my;
    
    // You can repel the particle by increasing the
    // particle's position by a fraction of dx & dy
    px+=dx/100;
    py+=dy/100;
    
    // And you can attract the particle by decreasing the
    // particle's position by a fraction of dx & dy
    px-=dx/100;
    py-=dy/100;
    

    这里带注释的代码和演示(为了便于理解而删除了缓动):

    &#13;
    &#13;
    // canvas related variables
    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var cw=canvas.width;
    var ch=canvas.height;
    function reOffset(){
      var BB=canvas.getBoundingClientRect();
      offsetX=BB.left;
      offsetY=BB.top;        
    }
    var offsetX,offsetY;
    reOffset();
    window.onscroll=function(e){ reOffset(); }
    window.onresize=function(e){ reOffset(); }
    
    ctx.fillStyle='skyblue';
    
    // mouse related variables
    var PI2=Math.PI*2;
    var mouseRadius=75;   // this is the mouse's radius of influence
    var mouseRadiusSquared=mouseRadius*mouseRadius;
    var mouseIsDown=false;
    var mx,my;
    
    
    // define a bunch of hex objects stored in an array
    var hexRadius=5;
    var hexPadding=5;
    var hexes=[];
    for(var y=hexRadius;y<ch;y+=hexRadius*2+hexPadding){
      for(var x=hexRadius;x<cw;x+=hexRadius*2+hexPadding){
        hexes.push({startingX:x,startingY:y,x:x,y:y});
      }}
    
    
    // start a continuously running ticker loop
    requestAnimationFrame(tick);
    
    
    // listen for mouse events
    $("#canvas").mousedown(function(e){handleMouseDown(e);});
    $("#canvas").mouseup(function(e){handleMouseUp(e);});
    
    
    // draw every hex in its current position
    function draw(){
      ctx.clearRect(0,0,cw,ch);
      ctx.beginPath();
      for(var i=0;i<hexes.length;i++){
        var h=hexes[i];
        ctx.moveTo(h.x,h.y);
        ctx.arc(h.x,h.y,hexRadius,0,PI2);
        ctx.closePath();
      }
      ctx.fill();
    }
    
    // create a continuously running ticker
    function tick(time){
    
      // update each hex position based on its 
      // position relative to the mouse
      for(var i=0;i<hexes.length;i++){
        var h=hexes[i];
        // calculate if this hex is inside the mouse radius
        var dx=h.x-mx;
        var dy=h.y-my;
        if(mouseIsDown && dx*dx+dy*dy<mouseRadiusSquared){
          // hex is inside mouseRadius
          // so mouseDown repels hex
          h.x+=dx/120;
          h.y+=dy/120;
        }else if(h.x==h.startingX && h.y==h.startingY){
          // hex is at startingX/Y & is not being repelled
          // so do nothing
        }else{
          // hex has moved off startingX/Y
          // but is no longer being repelled
          // so gravity attracts hex back to its startingX/Y
          dx=h.x-h.startingX;
          dy=h.y-h.startingY;
          h.x-=dx/60;
          h.y-=dy/60;            
        }
      }
    
      // redraw the hexes in their new positions
      draw();
    
      // request another tick
      requestAnimationFrame(tick);
    }
    
    
    // listen for mousedown events
    function handleMouseDown(e){
    
      // tell the browser we're handling this event
      e.preventDefault();
      e.stopPropagation();
    
      // calculate the mouse position
      mx=parseInt(e.clientX-offsetX);
      my=parseInt(e.clientY-offsetY);
    
      // set the mousedown flag
      mouseIsDown=true;
    }
    
    
    // listen for mouseup events
    function handleMouseUp(e){
    
      // tell the browser we're handling this event
      e.preventDefault();
      e.stopPropagation();
    
      // clear the mousedown flag 
      mouseIsDown=false;
    }
    &#13;
    body{ background-color: ivory; padding:10px; }
    #canvas{border:1px solid red;}
    &#13;
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    
    <h4>Press the mouse down to repel the particles.<br>Release to return particles to starting point.</h4>
    <canvas id="canvas" width=300 height=300></canvas>
    &#13;
    &#13;
    &#13;