javascript - JS Canvas 分别为网格元素设置动画

标签 javascript html 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();
        }
    }

我的最终目标是创建一个六边形网格,当鼠标光标在页面上移动时,这些六边形网格会远离鼠标光标,并具有一个影响区域。我不知道如何在每个六边形之间绘制一条路径,而且我在尝试为六边形制作动画时也遇到了问题。

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

我在想我应该尝试存储网格并在以后影响它,但我不确定我会怎么做,我也不认为 Canvas 是那样工作的。

我发现这几乎是我想做的,但我不明白它是如何工作的: http://codepen.io/soulwire/pen/Ffvlo

我现在可以很好地梳理它,如果有人可以引导我完成它,那就太好了:)

编辑:我已经在点后面绘制了一个网格,我也想操纵它。我仍然不明白上面链接的 codepen,这有点让我头疼。

最佳答案

您的链接应用了 2 个力:

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

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

数学原理是这样的:

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

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

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

关于javascript - JS Canvas 分别为网格元素设置动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28390481/

相关文章:

javascript - 使用 NPM 和 Watchify 编译多个脚本包

javascript - 通过 Javascript 功能实时编辑 HTML

html - Canvas (Kinetic.JS): multiple layers vs single layer approach

java - 如何使 Java Canvas 看起来从其容器中升起

javascript - 将 Javascript 变量作为图像传递给 PHP

javascript - 无法在 npm run build 上缩小代码

javascript - 将 View 模型对象传递给 jquery 变量

PHP + MySQL + HTML 在表格中显示不同的信息

html - 谷歌浏览器 v.30 : CSS overflow attribute on input elements cause other inputs to jump on focus state

javascript - 如何使 Canvas 对眼睛不可见但对 mousemove 事件不可见?