炒鸡简单的canvas粒子

要说canvas中最精妙的地方,那应该就是对像素操做的能力了,可能这也就是为何做为位图的canvas一直不会被svg比下去的缘由了。 俗话说,须弥芥子,是大小之说,也有以小见大之说,颗颗粒子,足以构建宏大效果。 这是一篇炒鸡简单的canvas粒子教程,主要是讲如何粒子特效的原理,一点运动中的公式。git

有所准备

首先,当咱们知道要作粒子的效果的时候,咱们要思考咱们如何来实现,并且还要尽量的面对咱们亲爱的对象,因而便有了以下的思考。github

  1. 要有粒子
  2. 粒子在运动,运动就须要速度
  3. 匀速运动/变速运动
  4. 运动以外还须要哪些处理

全局中的永恒

这里我定义了时间与粒子生成的数量,还有一个粒子池。canvas

也许会很奇怪,咱们在运动的过程当中每一帧都是时间,为何还要再设置这个时间,浏览器的渲染能够被看做正常流逝的时间,这里的time则是相对时间 若是感受晕晕的,浏览器

这里能够举个小李子:bash

光在世界中沿直线传播,你如今所能看到的月光是好久以前的月光,这就说明好久以前的月光一直在传播,同时也意味着你的一切动做都还在传播的过程当中,只要你的速度足够快,就能够追上你的过去。dom

开个小玩笑了,其实time的意思就是你的1s对于小球而言是2s,浏览器渲染设置的时间只是为了让你的视觉上看不出图像的卡顿svg

const time=2;
const num=20;
var dots=[];
复制代码

粒子类

function dot(x,y,vx,vy){
  //接收粒子点的坐标与方向速度量
  this.x=x;
  this.y=y;
  this.vx=vx;
  this.vy=vy;
  //随机粒子大小
  this.size=Math.ceil(Math.random()*3+2);
  this.ctx={};
}
  //粒子渲染
dot.prototype.render = function(ctx) {
  ctx.save();
  this.ctx=ctx;
  this.ctx.beginPath();
  this.ctx.fillStyle='lightgray';
  this.ctx.arc(this.x-this.size/2,this.y-this.size/2,this.size,0,Math.PI*2);
  this.ctx.closePath();
  this.ctx.fill();
  ctx.restore();
};
  //对当前粒子属性作逻辑计算
dot.prototype.update = function() {
  this.ctx.clearRect(0,0,canvas.width,canvas.heihgt);
  this.x=this.x+this.vx*time;
  this.y=this.y+this.vy*time;
  this.vx = (this.x < canvas.width && this.x > 0) ? this.vx : (-this.vx);
  this.vy = (this.y < canvas.height && this.y > 0) ? this.vy : (-this.vy);
  this.render(this.ctx);
};
复制代码

在当前粒子类中,我只给了速度的方向量,由于咱们只要求粒子作匀速运动,这里的计算公式则是x=vt(x:位移 v:平均速度 t:运动时间)ui

若是要对粒子施加力或者变速运动,则须要this.a=a来添加一个加速度的属性。而后根据加速度的方向作水平与垂直的分解,而且对速度的方向量产生做用,从而进行变速运动,这里的公式以下this

  1. v=at
  2. x=(v0+at/2)*t
    v0为初速度,a为加速度的方向量,x为方向上的位移

祸乱世界的粒子

for(let i=0;i<num;i++){
  var x=Math.ceil(Math.random()*canvas.width);
  var y=Math.ceil(Math.random()*canvas.height);
  var vx=Math.ceil(Math.random()*2);
  var vy=Math.ceil(Math.random()*2);
  var d=new dot(x,y,vx,vy);
  d.render(ctx);
  dots.push(d);
}
复制代码

经过对canvas的宽高进行随机取整来获取随机的坐标点。而且实例化咱们的粒子。而且推入粒子池中。 这里由于咱们在update方法中会直接调用render,因此咱们只须要在实例化的时候执行一次renderctx环境传入,后面就能够所有交给update来完成了。spa

躁动吧 粒子球

requestAnimFrame(anim);
function anim(){
  for(let i=0;i<dots.length;i++){
      dots[i].update();
  }
  requestAnimFrame(anim);
}
复制代码

这里咱们只须要对粒子池中的粒子进行数据持续更新,就可让粒子们跑起来了。

粒子的教程比较简单,但确是几乎全部粒子效果的依托,粒子已经能够生成,那么只须要让粒子在咱们的规定路径上运动,就能够达到咱们所须要的效果了。

拓展思惟

  1. 知乎背景的网状效果

    遍历全部粒子点,若是在范围内,则使用moveTo与llineTo来生成链接线。

  2. 粒子成字

    将文字先绘制在离屏canvas上,而后返回全部不透明像素点的坐标,遍历时能够直接遍历,也可使用widthheight来计算,若是当前点须要绘制,就生成粒子。

    这里说到像素点不透明,是由于在canvas上,你只要不设置,默认是不存在背景色,也就说,全部绘制的全部像素均可以经过判断其alpha值是否为0来判断,也能够经过设置alpha的阈值来将一些填充度不够的点给扔除。好比说当alpha对应为128的时候,透明度约为0.5,这也是为何不少人的博客里都用到了128这个判断值。

    还有不少的效果,粒子特效是一个很大的话题,如AE Unity等软件中都会有内置的粒子插件与外置的大量粒子效果插件。

后面还会写一些有些高度的粒子效果

不按期更新canvas与svg的相关技术教程,有实战型,也会有主原理型的,2d 2.5d 3d都会包含到,同时涉及的有 线性代数 物理 图形学等相关的基础知识。

本次demo源码:粒子效果

欢迎各位客官收藏关注,投硬币喂养。

同时感谢你们为我提出文中的不足与问题~

相关文章
相关标签/搜索