这是js实现的粒子动画,有两种模式,分别是zoom和line,它们对应的效果不同,但是原理都相同,具体分析如下:

部分程序如下:

        var p = this;
p.originParams = originParams;
p.params = params;
p.innerWidth = window.innerWidth;//页面视图区大小
p.innerHeight = window.innerHeight;
p.points = [];
p.pageXY = {pageX:p.innerWidth/2,pageY:p.innerHeight/2};
if(container[0] === '#') {
p.container = container.split('#')[1];
};
//获取canvas元素
p.canvas = document.getElementById(p.container);
//创建context对象
p.ctx = p.canvas.getContext('2d');
//初始化
p.init = function() {
p.canvas.width = p.innerWidth;
p.canvas.height = p.innerHeight;
p.drawBackground();
p.addOverlap();
p.initDrawPoint();
p.animation();
p.mouseEvent();
p.windowResize();
};
p.addOverlap=function(){
p.overlap=document.createElement('div');
p.overlap.style.width=p.innerWidth+'px';
p.overlap.style.height=p.innerHeight+'px';
p.overlap.style.position='absolute';
p.overlap.style.top='0px';
p.overlap.style.left='0px';
p.overlap.style.zIndex='100';
if(p.canvas.nextElementSibling){//??
p.canvas.parentNode.insertBefore(p.overlap,p.canvas.nextElementSibling);//insertBefore接收要插入的节点和作为参考的节点
}else{
p.canvas.parentNode.appendChild(p.overlap);
};
};
//粒子颜色
p.color = function() {
function random() {
return Math.round(Math.random() * 255);
};
this.r = random();
this.g = random();
this.b = random();//分别调用三次取随机值
this.a = random(1, 0.8);
this.rgba = 'rgba(' + this.r + ',' + this.g + ',' + this.b + ',' + this.a + ')';
return this;
};
//获取随机数
p.random = function(max, min) {
var min = arguments[1] || 0;
return Math.floor(Math.random() * (max - min + 1) + min);
};
//绘制背景图
p.drawBackground = function() {
if(!p.canvas) return;
p.ctx.fillStyle = '#000';
p.ctx.fillRect(0, 0, p.innerWidth, p.innerHeight);
};
//粒子
p.point = function() {//每个粒子包括颜色,坐标、半径
this.color = new p.color();
this.x = Math.random() * p.innerWidth;//随机坐标
this.y = Math.random() * p.innerHeight;
this.vx = p.random(10, -10) / 40;//步进,调用p.random
this.vy = p.random(10, -10) / 40;
this.r = p.random(3, 1);//半径,调用p.random,半径最大为3,最小为1,在这个范围内波动
this.scale = 1;//放大倍数
};
//初始化点
p.initDrawPoint = function() {
for(var i = 0; i < p.params.point; i++) {//所有点
var point = new p.point();
p.points.push(point);
p.ctx.beginPath();
p.ctx.fillStyle = point.color.rgba;
p.ctx.arc(point.x, point.y, point.r * point.scale, 0, Math.PI * 2, true);
p.ctx.fill();
};
p.ctx.closePath();
};
//点点连线
p.connect = function() {
function lineColor(p1, p2) {
var linear = p.ctx.createLinearGradient(p1.x, p1.y, p2.x, p2.y);//起点终点坐标
linear.addColorStop(0, p1.color.rgba);//开始的颜色
linear.addColorStop(1, p2.color.rgba);//结束的颜色
return linear;
};
for(var i = 0; i < p.params.point; i++) {
for(var j = 0; j < p.params.point; j++) {
var p1 = p.points[i];
var p2 = p.points[j];
if(Math.abs(p2.x - p1.x) < p.params.minDis && Math.abs(p2.y - p1.y) < p.params.minDis) {//两点之间距离小于一定程度才连线 p.ctx.beginPath();
p.ctx.lineWidth = 0.2;
p.ctx.strokeStyle = lineColor(p1, p2);//采用渐变,描边样式
p.ctx.moveTo(p1.x, p1.y);
p.ctx.lineTo(p2.x, p2.y);
p.ctx.stroke();//描边,使用的是strokeStyle
p.ctx.closePath();
};
};
};
};
p.lineto = function() {//和鼠标位置有关
function isInView(point) {
return Math.abs(point.x - p.pageXY.pageX) < p.params.mouseDis && Math.abs(point.y - p.pageXY.pageY) < p.params.mouseDis;
};
(function line() {
function lineColor(p1, p2) {
var linear = p.ctx.createLinearGradient(p1.x, p1.y, p2.x, p2.y);
linear.addColorStop(0, p1.color.rgba);
linear.addColorStop(1, p2.color.rgba);
return linear;
};
for(var i = 0; i < p.params.point; i++) {
for(var j = 0; j < p.params.point; j++) {
if(i != j) {
var p1 = p.points[i];
var p2 = p.points[j];
if(isInView(p1) && isInView(p2)) {
if(Math.abs(p2.x - p1.x) < p.params.minDis && Math.abs(p2.y - p1.y) < p.params.minDis) {
p.ctx.beginPath();
p.ctx.lineWidth = 0.2;
p.ctx.strokeStyle = lineColor(p1, p2);
p.ctx.moveTo(p1.x, p1.y);
p.ctx.lineTo(p2.x, p2.y);
p.ctx.stroke();
p.ctx.closePath();
};
};
};
};
};
})();
};
//无限循环动画
p.animation = function() {
p.ctx.clearRect(0, 0, p.innerWidth, p.innerHeight);
p.drawBackground();
for(var i = 0; i < p.params.point; i++) {
var point = p.points[i];
if(point.x < 0 || point.x > p.innerWidth) {//当小圆球碰到矩形壁以后反弹
point.vx = -point.vx;
};
if(point.y < 0 || point.y > p.innerHeight) {
point.vy = -point.vy;
};
p.ctx.beginPath();
p.ctx.fillStyle = point.color.rgba;
point.x += point.vx; //小圆球不断移动
point.y += point.vy;
p.ctx.arc(point.x, point.y, point.r * point.scale, 0, Math.PI * 2, true);
p.ctx.fill();
};
if(p.params.effect == 'zoom') {
p.connect();//将小球与小球用线连接,鼠标移动事件定义在mouseEvent中
} else if(p.params.effect == 'line') {
p.lineto();//该函数与鼠标位置有关,通过鼠标事件传入鼠标位置,在该位置附近连线
};
requestAnimationFrame(p.animation);
};
//鼠标事件
p.mouseEvent = function() {
p.overlap.addEventListener('mousemove', function(e) {//鼠标指针移动时触发div中的事件
var e = e || window.event;
var pageX = (e.clientX + document.body.scrollLeft || e.pageX) - this.offsetLeft;//offsetLeft指div到边框??
var pageY = (e.clientY + document.body.scrollTop || e.pageY) - this.offsetTop;
if(p.params.effect == 'zoom'){
for(var t = 0; t < p.params.point; t++) {
var point = p.points[t];
if(Math.abs(point.x - p.pageXY.pageX) < p.params.minDis && Math.abs(point.y - p.pageXY.pageY) < p.params.minDis) {//鼠标附近的点
point.scale = 5;
} else {
point.scale = 1;
};
};
};
p.pageXY.pageX = pageX;
p.pageXY.pageY = pageY;
});
p.overlap.addEventListener('mouseout', function(e) {//鼠标指针位于一个元素上方,然后用户将其移入另一个元素时触发
if(p.params.effect == 'zoom'){//zoom鼠标移出div都变为原来的比例
for(var i = 0; i < p.params.point; i++) {
var point = p.points[i];
if(point.scale != 1) {
point.scale = 1;
};
};
}else{
p.pageXY.pageX=p.innerWidth/2;//line方式鼠标移出div自动定位到中心
p.pageXY.pageY=p.innerHeight/2;
};
});
};
p.windowResize = function() {
window.addEventListener('resize', p.init);
};
p.init();
return p;
};
//兼容requestAnimFrame
window.requestAnimationFrame = (function() {//requestAnimationFrame??
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function(callback) {//前面三个都不支持则采用该函数
window.setTimeout(callback, 1000 / 60);
};
})();

【JavaScript】particle的更多相关文章

  1. 【javascript】html5中使用canvas编写头像上传截取功能

    [javascript]html5中使用canvas编写头像上传截取功能 本人对canvas很是喜欢,于是想仿照新浪微博头像上传功能(前端使用canvas) 本程序目前在谷歌浏览器和火狐浏览器测试可用 ...

  2. 【JavaScript】出现即使设置了ID也获取不到的可能原因与window.onload

    有时候.在JavaScript中.即使设置了ID也有可能出现document.getElementById()获取不到的情况,然后你就開始想document是否写错之类的.事实上根本就不是你的代码的大 ...

  3. 【JavaScript】我的JavaScript技术总结第一篇——编程细节

    遍历数组 for (var i=0, l=arr.length; i<l; i++) 这样写的一个好处就是让每次循环少一步获取数组对象长度的操作,数组长度越长,价值越明显. 判断变量的真假 if ...

  4. 【JavaScript】下大雪

    引用[JavaScript]满天星的代码,稍作修改的结果: function drawStars() { for (i = 1; i < 100; ++i) { ctx.fillText(&qu ...

  5. 【JavaScript】JavaScript中的replaceAll

    JavaScript中是没有replaceAll的.仅仅有replace,replace仅仅能替换字符中的第一个字符.并且这个replace里面不支持正則表達式,以达到replaceAll的目的. 只 ...

  6. 【JavaScript】Leetcode每日一题-在D天内送包裹的能力

    [JavaScript]Leetcode每日一题-在D天内送包裹的能力 [题目描述] 传送带上的包裹必须在 D 天内从一个港口运送到另一个港口. 传送带上的第 i 个包裹的重量为 weights[i] ...

  7. 【JavaScript】Leetcode每日一题-青蛙过河

    [JavaScript]Leetcode每日一题-青蛙过河 [题目描述] 一只青蛙想要过河. 假定河流被等分为若干个单元格,并且在每一个单元格内都有可能放有一块石子(也有可能没有). 青蛙可以跳上石子 ...

  8. 【JavaScript】Leetcode每日一题-平方数之和

    [JavaScript]Leetcode每日一题-平方数之和 [题目描述] 给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a2 + b2 = c . 示例1: 输入:c = 5 ...

  9. 【JavaScript】Leetcode每日一题-二叉搜索树的范围和

    [JavaScript]Leetcode每日一题-二叉搜索树的范围和 [题目描述] 给定二叉搜索树的根结点 root,返回值位于范围 [low, high] 之间的所有结点的值的和. 示例1: 输入: ...

随机推荐

  1. C# 工具类之数据库链接

     一.SQL Server 相关 /// <summary> /// 数据库的通用访问代码 /// 此类为抽象类, /// 不允许实例化,在应用时直接调用即可 /// </summa ...

  2. java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/images/media/20 from pid=711, uid=10074 requires android.permission.READ_

    java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider ur ...

  3. Hadoop配置要点必看

    hadoop 配置要点 软件 版本 java 1.8.0_151 hadoop 2.6.1 part1 $HADOOP_HOME/etc/hadoop 目录下配置参数. slaves 配置从节点 ya ...

  4. 撩课-Python-每天5道面试题-第4天

    一. for循环和while循环中的else代表什么意思? 当for循环和while循环顺利的遍历完成时, 就会执行else分支 如果循环过程中, 碰到continue, 只要没有打断循环, 就会继续 ...

  5. 【SSH网上商城项目实战22】获取银行图标以及支付页面的显示

        转自: https://blog.csdn.net/eson_15/article/details/51452243 从上一节的小demo中我们搞清楚了如何跟易宝对接以及易宝的支付流程.这一节 ...

  6. linux ssh免密登陆

    大致流程: 两台linux系统A B 如果A要登陆到B 1.生成A的密钥对 2.将A的公钥拷贝到B的authorized_keys中即可 可以使用命令:ssh-copy-id -i ~/.ssh/id ...

  7. Windows命令行方式执行OracleSQL脚本

    调用格式 sqlplus user/pwd@orcl @F:\DB_BAKFile\createpro.sql>>F:\DB_BAKFile\log\createpro.log SQL脚本 ...

  8. CSS之Flex 布局

    Flex 布局教程:语法篇 网页布局(layout)是 CSS 的一个重点应用. 布局的传统解决方案,基于盒状模型,依赖 display 属性 + position属性 + float属性.它对于那些 ...

  9. sql: Oracle 11g create procedure

    CREATE OR REPLACE PROCEDURE proc_Insert_BookKindList ( temTypeName nvarchar2, temParent int ) AS nco ...

  10. 洛谷P4781 【模板】拉格朗日插值(拉格朗日插值)

    题意 题目链接 Sol 记得NJU有个特别强的ACM队叫拉格朗,总感觉少了什么.. 不说了直接扔公式 \[f(x) = \sum_{i = 1}^n y_i \prod_{j \not = i} \f ...