这个动画在很早之前就见过,当时就没迷住了。最近在学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)的更多相关文章

  1. 2015.4.23 贪吃蛇、canvas动画,各种上传工具,url信息匹配以及最全前端面试题等

    1.面向对象贪吃蛇   2.css中:hover 改变图片 页面加载完 第一次鼠标移入会闪一下 这是为啥? 解决方法:你把两张图合成一张图或者是先把图片加载到页面上,然后再hover出来. 解析:图片 ...

  2. HTML动画分类 HTML5动画 SVG库 SVG工具 Canvas动画工具

     1.js配合传统css属性控制,可以使用setTimeout或者高级的requestAnimationFrame 2.css3 3.svg 4.canvas(当然,这个还是要配合js)   也许这么 ...

  3. 7 个顶级的 HTML5 Canvas 动画赏析

    HTML5确实是一项改革浏览器乃至整个软件行业的新技术,它可以帮助我们Web开发者很方便地在网页上实现动画特效,而无需臃肿的Flash作为支撑.本文分享7个顶级的HTML5 Canvas 动画,都有非 ...

  4. 8个经典炫酷的HTML5 Canvas动画欣赏

    HTML5非常强大,尤其是Canvas技术的应用,让HTML5几乎可以完成所有Flash能完成的效果.本文精选了8个经典炫酷的HTML5 Canvas动画欣赏,每一个都提供全部的源代码,希望对你有所帮 ...

  5. 7个惊艳的HTML5 Canvas动画效果及源码

    HTML5非常强大,尤其是现在大部分浏览器都支持HTML5和CSS3,用HTML5制作的动画也多了起来.另外,Canvas上绘制图形非常简单,本文就分享了一些强大的HTML5 Cnavas动画,一起来 ...

  6. 《FLASH CC 2015 CANVAS 中文教程》——1、导出canvas动画,文件结构浅析

    注::如果你对 FLASH 这个软件操作不够熟悉,建议你可以先看看FLASH动画之类的书. :FLASH CC 在文中直接简称为CC. :以下所以文章中所说的快捷键 如果你按了不起作用,请检查是否有其 ...

  7. Html5 Canvas动画旋转的小方块;

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...

  8. 【原创】测试不同浏览器播放canvas动画的平滑程度

    Canvas无疑是HTML5开放式网络平台最激动人心的技术之一.目前,除了IE8以外,各类浏览器的新版本都支持HTML5 Canvas. 程序员需要通过Javascript调用Canvas API.基 ...

  9. HTML5 Canvas动画效果演示

    HTML5 Canvas动画效果演示 主要思想: 首先要准备一张有连续帧的图片,然后利用HTML5 Canvas的draw方法在不同的时间 间隔绘制不同的帧,这样看起来就像动画在播放. 关键技术点: ...

随机推荐

  1. 【TED】如何掌握你的自由时间

    [TED]如何掌握你的自由时间 生活 某天翻阅自己原来记录的有道云笔记,发现自己在学校的时候,要求自己每周看三个TED视频,并写一些看后的总结,随意翻阅了下,就发现当时做的好的一些笔记,现在一看就能想 ...

  2. 浅谈 虚方法(virtual)

    虚方法 理解:从字面意思来讲,"虚",可有可无,子类对父类的某种方法的重写,可以重写,也可以不重写. 虚方法,顾名思义(装个13),就是某种方法. 用法:public virtua ...

  3. python数据处理——numpy_2

    上一次的学习了numpy的一些基础操作,今天接着学习numpy的高级索引.轴对换数值转置以及作图. #花式索引 import numpy as np ''' t = np.empty((8,4)) # ...

  4. 深入tornado中的ioLoop

    本文所剖析的tornado源码版本为4.4.2 ioloop就是对I/O多路复用的封装,它实现了一个单例,将这个单例保存在IOLoop._instance中 ioloop实现了Reactor模型,将所 ...

  5. 懵懂oracle之存储过程

    作为一个oracle界和厨师界的生手,笔者想给大家分享讨论下存储过程的知识,因为在我接触的通信行业中,存储过程的使用还是占据了一小块的地位. 存储过程是什么?不得不拿下百度词条的解释来:"存 ...

  6. 使用vs code实现git同步

    用了git最方便的就是项目同步管理,回到家打开vscode只需要点击一下pull就能全部同步过来.是不是很方便....毕竟之前我都是拿u盘拷贝回家或者存到云盘再下载下来..   我这里用的是国内的码云 ...

  7. 学好php可以做的事情真多!

    学好php能做什么?其实学好php能做的事情很多! 一. 学好php可以就业 1:大中小公司通吃. 现在几乎所有有前途的公司都会在互联网上安家.只要在网上安家,就需要找这些方面的技术人员,而且很多公司 ...

  8. SCP“免密” 远程COPY较多文件

    一.linux脚本实现自动输入密码 使用Linux的程序员对输入密码这个举动一定不陌生,在Linux下对用户有严格的权限限制,干很多事情越过了权限就得输入密码,比如使用超级用户执行命令,又比如ftp. ...

  9. .net使用RabbitMQ

    前面的两篇博文算是把RabbitMQ的基础了解了下,今天学习.Net 中RabbitMQ的使用.原本这篇博文是应该上周写的,可在自己使用的过程中出现了一个问题bug:就是在连接服务端时,一直报下面的错 ...

  10. ④JavaScript格式化时间戳

    这部分代码是按照网上的教程写的,忘记在哪里看到了