canvas——粒子系统(1)

这个动画在很早之前就见过,当时就没迷住了。最近在学canavs动画,动手实现了一下。代码在这里。展示效果在这里。
这属于粒子系统的一种,粒子系统就是需要管理一堆粒子嘛,动画实现的关键在于,遍历这些粒子,并更新它们的位置。
粒子
每个粒子都需要包含自己的横纵坐标想x、y,半径r,各分量上的加速度ax、ay,速度vx、vy,还有所属的场景owner,这里的粒子加速度均为0。

// 父类
class Sprite {
constructor(args={}) {
this.x = args.x || 0;
this.y = args.y || 0;
this.vx = args.vx || 0;
this.vy = args.vy || 0;
this.ax = args.ax || 0;
this.ay = args.ay || 0;
} moveTo(x, y) {
this.x = x;
this.y = y;
} update() {
this.vx += this.ax;
this.vy += this.ay; this.x += this.vx;
this.y += this.vy;
} render() {
return true;
}
}
// 粒子
class Particle extends Sprite{
constructor(args) {
super(args);
this.owner = args.owner;
this.r = args.r || 10;
this.color = args.color || 'black'; this.adjust = this.adjust.bind(this);
} update() {
super.update();
if(this.x < this.r || this.x + this.r > this.owner.w) {
this.vx *= -1;
this.x = this.adjust(0, this.owner.w, this.x);
} if(this.y < this.r || this.y + this.r > this.owner.h) {
this.vy *= -1;
this.y = this.adjust(0, this.owner.h, this.y);
}
} render(ctx) {
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, false);
ctx.closePath();
ctx.fill();
} adjust(min, max, v) {
return v > max ? max : (v < min ? min : v);
}
}

父类的update()中用于改变对象的坐标,particle类的update()在调用了父类的update方法之后,进行边界检测。
边界检测
边界检测属于碰撞检测的一种。在改变粒子位置之后,对粒子进行边界检测,防止粒子逃出canvas哦。本例中的粒子是圆形的,可以通过粒子中心点与边界之间的距离进行判断,若小于粒子自身半径,则对粒子坐标进行修正,确保粒子始终位于canvas中。

/*
* this.x 粒子横坐标
* this.y 粒子纵坐标
* this.r 粒子半径
* this.owner.w 粒子所在场景(canvas)宽度
* this.owner.h 粒子所在场景(canvas)高度
*/
if(this.x < this.r || this.x + this.r > this.owner.w) {
this.vx *= -1;
this.x = this.adjust(0, this.owner.w, this.x);
} if(this.y < this.r || this.y + this.r > this.owner.h) {
this.vy *= -1;
this.y = this.adjust(0, this.owner.h, this.y);
}

当粒子坐标超出边界时,使用adjust()重置粒子坐标,确保粒子在canvas内。
adjust(min, max, v) {
return v > max ? max : (v < min ? min : v);
}
粒子系统
粒子系统就是对粒子进行管理的。
this.nodes = []; // 保存粒子
this.edges = []; // 粒子成对保存,用于连线
存储edges时,使用双层循环,内循环n的从i + 1开始,避免重复保存。

for(let i = 0, len = this.nodes.length; i < len; ++i) {
for(let n = i + 1; n < len; ++n) {
this.edges.push({
from: this.nodes[i],
to: this.nodes[n]
})
}
}

计算两个粒子之间的距离。
lengthOfEdge(edge) {
let w = Math.abs(edge.from.x - edge.to.x),
h = Math.abs(edge.from.y - edge.to.y);
return Math.sqrt(w * w + h * h);
}
粒子间距离越短,连线越粗、越深。
this.ctx.lineWidth = (1 - l / this.threshold) * 2.5;
this.ctx.globalAlpha = 1 - l / this.threshold;
超出一定距离就不连线。
let l = this.lengthOfEdge(edge);
if(l > this.threshold) {
return;
}
鼠标事件
这里为了与用户有互动,加入了鼠标事件。当鼠标在canvas内移动时,第一个粒子nodes[0]的跟随鼠标移动。当鼠标静止或者在canvas外时,则按照原来的速度进行移动。

mouserEnter(e) {
this.mouse = this.nodes[0];
}
mouseMove(e) {
this.mouse.x = e.offsetX;
this.mouse.y = e.offsetY;
}
mouseLeave() {
this.mouse = null;
}

至于动画的更新,建议使用requestAnimationFrame()。
canvas——粒子系统(1)的更多相关文章
- canvas粒子系统的构建
前面的话 本文将从最基本的imageData对象的理论知识说开去,详细介绍canvas粒子系统的构建 效果演示 下面是实例效果演示,博文结尾有全部源码 imageData 关于图像数据imageDat ...
- HTML5的新结构标签
在之前的HTML页面中,大家基本上都是用了Div+CSS的布局方式.而搜索引擎去抓取页面的内容的时候,它只能猜测你的某个Div内的内容是文章内容容器,或者是导航模块的容器,或者是作者介绍的容器等等.也 ...
- canvas动画——粒子系统(1)
这个动画在很早之前就见过,当时就没迷住了.最近在学canavs动画,动手实现了一下.代码在这里.展示效果在这里. 这属于粒子系统的一种,粒子系统就是需要管理一堆粒子嘛,动画实现的关键在于,遍历这些粒子 ...
- canvas绘图基础及基于粒子系统的雪花飘落
canvas是html中的一个元素,可以通过js操控绘图! 可以绘制各种图形,各种填充样式! 绘制时可以进行旋转,缩放,平移,但并不是很灵活! 有一对比较好用的方法是save restore! sav ...
- 粒子系统(二):Canvas绘制精美图案
准备 IDE:Visual Studio Code Language:JavaScript / ECMAScript 6+ GitHub:Natural2D.JS 本文主要讲述 Particles - ...
- Three.js开发指南---粒子和粒子系统(第七章)
使用粒子可以很容易的创建很多细小的物体,例如雨滴雪花等 本章主要内容: 1 使用ParticleBasicMaterial(基础粒子材质)来创建和设计粒子 2 使用ParticleSystem来创建一 ...
- three.js入门系列之粒子系统
其实代码很简单,也很容易懂(我用的是r99版本的three.js,目前网上大多数demo是60或者80的版本,其中的一些api已经废弃,如下是r99版本支持的写法): 注:渲染器是WebGl渲染器 如 ...
- canvas绘制经典星空连线效果
来自:https://segmentfault.com/a/1190000009675230 下面开始coding:先写个canvas标签 <canvas height="620&qu ...
- 基于canvas与原生JS的H5动画引擎
前一段时间项目组里有一些H5动画的需求,由于没有专业的前端人员,便交由我这个做后台的研究相关的H5动画技术. 通过初步调研,H5动画的实现大概有以下几种方式: 1.基于css实现 这种方式比较简单易学 ...
随机推荐
- [Grid Layout] Use auto-fill and auto-fit if the number of repeated grid tracks is not to be def
What about the situation in which we aren’t specifying the number of columns or rows to be repeated? ...
- Android addTextChangedListener(文本监听)参数解释及实现EditText字数监听
由于最近做项目要检测EditText中输入的字数长度,从而接触到了Android中EditText的监听接口,TextWatcher.它有三个成员方法,第一个after很简单,这个方法就是在EditT ...
- erlang 符号相关基本语法
http://blog.csdn.net/anghlq/article/details/6803332 ErLang语法约定: 大写字母开头的名字(比如Address),表示一个变量,包括参数.局部变 ...
- C++ Primer章课后编程问题
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZ3V1Z2xlMjAxMA==/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...
- yii2 实现无极限分类
在商城项目或者其他的项目中无极限分类是非常常见的场景 那么许多人都会这样干 利用递归每次查询数据库,说来惭愧,我以前也是这样干的 总有点误人子弟的感觉 这样做在数据量大的情况下会有一定的延迟 publ ...
- WPF中PasswordBox控件的Password属性的数据绑定
原文:WPF中PasswordBox控件的Password属性的数据绑定 英文原文:http://www.wpftutorial.net/PasswordBox.html 中文原文:http://bl ...
- 一个2013届毕业生(踏上IT行业)的迷茫(3)
高中,是校园题材中出现最多的角色,但我的高中缺非常灰淡.我上的高中在我们镇上,记得在上小学的时候我哥在高中,我每次从学校门口过的时候都感觉高中好大,门口好漂亮,但是我从来都没敢进去.就在2006年我以 ...
- 电讯“情趣me”为什么命途多舛?
古人有句话叫做战争"鼓作气,再而衰,三而竭",意思是打仗必须"一气呵成".才干发挥最大实力,取得最好的战绩.所谓商场如战场,经商也是如此,近期,中国电信 ...
- PHP中遍历关联数组的方法
下面介绍PHP中遍历关联数组的三种方法:foreach <?php $sports = array( 'football' => 'good', 'swimming' => 'ver ...
- 在IIS上部署.net core的webapi项目 以及502.5错误的两种解决方法
首先要在服务器上面安装.net core https://github.com/dotnet/core/tree/master/release-notes/download-archives 这里面有 ...