上一篇文章中,咱们讲解了最基础的粒子动画,实现了在浏览器中跑来跑去的粒子以及讲解了粒子的一些常见特效的原理。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
欢迎各位客官收藏关注,投硬币喂养。
欢迎你们为我提出不足与错误~