Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
165 views
in Technique[技术] by (71.8m points)

javascript - JS Canvas animate grid elements individually

I'm generating a grid of hexagons by using a for loop and I'm having some issues

    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();
        }
    }

My end goal is to create a grid of hexagons that move away from the mouse cursor when it's moving around the page, with an area of influence. I can't work out how to draw a path between each of the hexagons and I'm also having an issue with trying to animate the hexagons.

I'm still a canvas newbie, I went through the tutorials on Mozilla's developer network and all of the animations were on singular objects, not objects generated in a grid.

I was thinking that I should try and store the grid and affect it later but I'm not sure how I would go about that, I also don't think canvas works like that.

I found this which is pretty much what I want to do but I can't understand how it works: http://codepen.io/soulwire/pen/Ffvlo

I'm fine combing through it now, if anyone could walk me through it that would be great :)

Edit: I've since gotten a grid drawn behind the dots, I'd like to manipulate this too. I still don't understand the codepen linked above, it's a little over my head.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your link applies 2 forces:

  1. Particles near the mouse are repelled. More specifically, if the particles centerpoint is near the mouse centerpoint, then the particle is repelled along the line between the two centerpoints.

  2. Particles not near the mouse are attracted back to their original positions. More specifically, the particles move toward their original centerpoint along the line between their current centerpoint and their original centerpoint.

The math works like this:

// 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;

Here's annotated code and a Demo (easing removed for ease of understanding):

// 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;
}
body{ background-color: ivory; padding:10px; }
#canvas{border:1px solid red;}
<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>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...