炒雞簡單的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源碼:粒子效果

歡迎各位客官收藏關注,投硬幣餵養。

同時感謝你們爲我提出文中的不足與問題~

相關文章
相關標籤/搜索