上一篇文章中,咱們講解了最基礎的粒子動畫,實現了在瀏覽器中跑來跑去的粒子以及講解了粒子的一些常見特效的原理。javascript
咱們把全部的運動公式都封裝在了dot類中,雖然說實現了咱們的當時需求,可是若是引伸到一些方向性的東西的時候,就會顯得蒼白而無力。java
向量確實是一個神奇的東西,當座標系肯定了以後,向量不只僅能夠看做是一個座標點,還能夠看作是一段距離,同時還具備方向性,這就對於咱們在平面中的定向操做就提供了很大的幫助。git
定義一個二維向量類github
function vector2(x,y) {
//當前的座標的x,y
this.x=x;
this.y=y;
}複製代碼
向量的移動canvas
當x2
與y2
都爲0的時候,也就是存在於座標原點時,相減以後還會是(x1,y1)
,這也是爲何我說它不只能夠表明一個座標,還能夠表明一段距離瀏覽器
vector2.prototype.move = function(vec2) {
this.x+=vec2.x;
this.y+=vec2.y;
};複製代碼
把向量單位化svg
單位向量,能夠理解成在一段向量上,長度爲1的向量測試
vector2.prototype.normalize = function(vec2) {
var x=vec2.x-this.x;
var y=vec2.y-this.y;
//以上是爲了將當前座標轉換爲原點,從而生成一段新的向量
return {
//返回一個單位向量
x:x/Math.sqrt(x*x+y*y),
y:y/Math.sqrt(x*x+y*y)
}
};複製代碼
若是對於向量不熟悉的能夠去看一看向量的公式,也許你看着會有一點暈,那麼我來舉一個例子。動畫
(1,1)
這是一個二維的向量,我能夠用它來表明一個座標,也能夠表明它到原點的距離,同時也能夠表明從原點到該點的方向。ui
到目前,一個簡單的向量類就已經足夠咱們去了解向量在圖形中的運用了。
如今,咱們就能夠對以前的粒子類進行重寫
當粒子趕上向量
function dot(x,y,ax=0,ay=0,color="black") {
//用向量來替代以前的純座標
this.site=new vector2(x,y);
//初始時的目標座標向量既是當前座標向量
this.end=new vector2(x,y);
//速度所有交由系統來調整
this.vx=0;
this.vy=0;
//加速度受外界力影響
this.ax=ax;
this.ay=ay;
this.color=color;
//設置水平與豎直方向的值,具體做用下面有講
this.direction={
hor:0,
ver:0
}
this.ctx={};
}複製代碼
在實現的時候,咱們須要知道什麼是受咱們直接影響的,什麼是受咱們間接影響的,這樣能夠能夠在實現的實現的時候更具備聯動性,把更多的計算交由計算機去處理,能夠大大避免一些沒必要要的誤操做。
最終點的設置
dot.prototype.setEnd = function(vec2) {
this.end=vec2;
this.vx=this.site.normalize(this.end).x;
this.vy=this.site.normalize(this.end).y;
if(vec2.x>this.site.x){this.direction.hor=1}
if(vec2.x<this.site.x){this.direction.hor=-1}
if(vec2.y>this.site.y){this.direction.ver=-1}
if(vec2.y<this.site.y){this.direction.ver=1}
};複製代碼
這裏會發現咱們的方向速度量是取的位移向量的單位向量,這裏的緣由是X=VT
,當時間必定時,速度能夠視做位移上的單位距離,而後將其方向化,也就得到了方向速度。
這裏我將粒子的初始位置與目標位置作了對比,得到了相對而言的上下或者左右,而且使用1
或者-1
來分別代替下右跟上左,有部分人不知道這裏爲何是下右跟上左,這是由於在屏幕上的y軸的計算是如下方問正方向的,這也爲何咱們在繪製的時候是用(100,100)
而不是(100,-100)
粒子的移動
dot.prototype.move = function() {
this.vy+=this.ay*t;
this.vx+=this.ax*t;
var hor="";
var ver="";
//對取整的方式進行判斷
switch (this.direction.hor) {
case 1:
hor='floor';
break;
case 0:
hor='floor';
break;
case -1:
hor='ceil';
default:
break;
}
switch (this.direction.ver) {
case 1:
ver='ceil';
break;
case 0:
ver='floor';
break;
case -1:
ver='floor';
default:
break;
}
if(Math[hor](this.site.x)!=this.end.x||Math[ver](this.site.y)!=this.end.y){
this.site.move(new vector2(this.vx,this.vy));
}
};複製代碼
移動的基本公式上一節也有基礎的介紹,這裏直接用的是帶加速度的,v=v0+at
(v0是初速度,v是勻變速t時間以後的速度)
在位置判斷的時候我使用了向下取整的方法,是由於在作單位向量的時候會出現帶根號的數,爲了便於判斷,咱們就須要對位置的座標進行取整,這個時候,咱們就須要根據粒子點在目標點的方位來決定是向上仍是向下取整。
取整以後就能夠進行判斷是否達到目標位置,若是沒有就會繼續調用move
的命令來不斷更新座標位置。
注意:
須要注意的是,我進行了取整,這也就意味着目標值要是整數,像素不存在小數位的像素,可是計算機在渲染如1.5px的時候,仍是渲染出一些奇怪的東西,能夠用如下的代碼作一下測試,你就清楚那不存在的小數位像素究竟是什麼。
ctx.fillStyle='red';
ctx.fillRect(1,2,1,1);
ctx.fillRect(1,1,1.5,1);
ctx.fillRect(1,3,1.2,1);
ctx.fill();複製代碼
後續工做
再以後,就是重複上一節的內容,將粒子實現渲染與更新,若是不清楚的能夠去看個人上一篇文章。
到目前爲止,咱們已經實現的粒子特效中最主要的部分,咱們能夠利用這個粒子類來實現粒子幾乎常見運動,如 勻速運動 勻變速/非勻變速運動 圓周運動 甚至是軌跡運動
是否是感受那些看起來飛來飛去的特效開始有邏輯可循了
不按期更新canvas與svg的相關技術教程,有實戰型,也會有主原理型的,2d 2.5d 3d都會包含到,同時涉及的有 線性代數 物理 圖形學等相關的基礎知識。
相關源碼:vector2
歡迎各位客官收藏關注,投硬幣餵養。
歡迎你們爲我提出不足與錯誤~