使用HTML5 Canvas创建动态粒子网格动画

  particles = [];

  for (let i = 0; i < opts.particleAmount; i++){

  particles.push( new Particle() );

  }

  window.requestAnimationFrame(loop);

  }

  在调用 loop 函数之前, setup 函数会创建一个由一系列粒子组成的 粒子 数组,这里使用 requestionAnimationFrame 来创建循环动画。

  loop 函数看起来是这个样子的:

  function loop(){

  window.requestAnimationFrame(loop);

  drawArea.clearRect(0,0,w,h);

  for (let i = 0; i < particles.length; i++){

  particles[i].update();

  particles[i].draw();

  }

  }

  loop 函数会清除 canvas 画布,更新每个粒子的位置,然后再绘制粒子;这里使用requestAnimationFrame() 来刷新、创建动画。

  设置了相关常量、变量,并初始化了 resizeReset 函数后,调用 setup 函数开始运行动画:

  const canvasBody = document.getElementById("canvas"),

  drawArea = canvasBody.getContext("2d");

  let delay = 200, tid;

  resizeReset();

  setup();

  到了这一步,动画看起来就是一系列点在 canvas 画布里面来回移动:

  动画效果可以去 CodePen 上查看Dudley Storey ( @dudleystorey )的 《使用HTML5的canvas创建动态点动画》 。

  为了创建网状结构,我们需要增加一点代码。

  创建线条

  为了绘制线条, loop() 函数需要添加些代码,变成下面这个样子:

  function loop(){

  window.requestAnimationFrame(loop);

  drawArea.clearRect(0,0,w,h);

  for (let i = 0; i < particles.length; i++){

  particles[i].update();

  particles[i].draw();

  }

  for (let i = 0; i < particles.length; i++){

  linkPoints(particles[i], particles);

  }

  }

  每个粒子都会调用 linkPoints 函数,这个函数会调用 checkDistance 函数:

  let checkDistance = function(x1, y1, x2, y2){

  return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));

  };

  checkDistance 函数决定了每个点与点之间的距离;如果距离小于 checkDistance,那么线条的 透明度 就会被设置成大于0,并且线条会在匹配的点之间重新绘制。

  在继续之前,先分解下 rgb 颜色 :

  `let rgb = opts.lineColor.match(/\d+/g);``

  linkPoints 函数用来检测每一个点相对于剩下其他点的距离(等同于函数的"hubs"参数),然后使用 模板字面量 按照相应的 透明度 来绘制线条:

  let linkPoints = function(point1, hubs){

  for (let i = 0; i < hubs.length; i++) {

  let distance = checkDistance(point1.x, point1.y, hubs[i].x, hubs[i].y);

  let opacity = 1 - distance / opts.linkRadius;

  if (opacity > 0) {

  drawArea.lineWidth = 0.5;

  drawArea.strokeStyle = `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, ${opacity})`;

  drawArea.beginPath();

  drawArea.moveTo(point1.x, point1.y);

  drawArea.lineTo(hubs[i].x, hubs[i].y);

  drawArea.closePath();

  drawArea.stroke();

  }

  }

  }

  结论

  使用ES6是非常高效的,我也鼓励你在脚本上去尝试各个设置选项。

  需要指出的是:如果添加过多的点和/或过多的连接距离(连接距离会创建过多的线条),动画也会扛不住。当视口变窄时最好降低粒子的运动速度:粒子的尺寸越小,在愈加狭窄空间内的移动速度貌似会越快。