ZRender实现粒子网格动画实战

注:本博文代码基于ZRender 3.4.3版本开发,对应版本库地址:ZRender 库。


效果


实现分析

通过上面显示的效果图,可以看出,这种效果就是在Canvas中生成多个可移动的点,然后根据点之间的距离来确定是否连线,思路比较简单。

实现问题:

  • 保持Canvas 100%显示
  • resize时,自动调节Canvas尺寸和内部变量
  • 生成圆点
  • 实现圆点的移动,及边界处理
  • 实现原点的直线连接

Canvas设置

html:

<canvas id="main"></canvas>

css:

#main{position: absolute; //用于100%填充left:0;top:0;background: #000;z-index: -1; //方便做背景层使用}

ZRender部分

这里主要用到的形状就是CircleLine,先引入这两个组件:

['zrender','zrender/graphic/shape/Circle','zrender/graphic/shape/Line'], 
function(zrender, Circle, Line){}

设置全局及配置项用到的变量

var winH = window.innerHeight; //同步页面宽、高
var winW = window.innerWidth; //同步页面宽、高var opts = { //可配置参数background: '#000', //Canvas背景色paricalRadius: 2, //粒子半径paricalColor: 'rgb(0, 255, 0)', //粒子颜色lineColor: 'rgb(0, 255, 0)', //连线颜色joinLineDis: 300, //粒子间连线的要求距离particalAmount: 30, //生成的粒子数量speed: 1, //粒子速度
};
var tid; //setTimeout id,防抖处理
var particals = []; //用于存储partical对象

初始化ZRender

var zr= zrender.init(main, {width: winW, height: winH});zr.dom.style.backgroundColor = opts.background; //设置背景色

窗口 resize 处理

window.addEventListener('resize', function(){clearTimeout(tid);var tid = setTimeout(function(){ //防抖处理winW = zr.dom.width = window.innerWidth;winH = zr.dom.height = window.innerHeight;zr.refresh();}, 300); //这里设置了300ms的防抖间隔
}, false);

效果:



创建粒子类 Partical

总结一下这个类,需要以下属性:

  • 坐标位置 x, y
  • 粒子速度
  • 粒子移动角度
  • 粒子颜色
  • 粒子半径
  • 粒子的角度方向变量
  • 粒子的ZRender形状实例

方法:

  • 更新位置坐标
  • 划线

这边直接用ES6的语法来创建类:

class Partical {}

构造器:

constructor(){this.lines = [], //用于存储连线//粒子坐标初始化this.x = winW * Math.random();this.y = winH * Math.random();this.speed = opts.speed + Math.random(); //这个random可不加,主要是为了制作不同的速度的this.angle = ~~(360 * Math.random());this.color = opts.paricalColor;this.radius = opts.paricalRadius + Math.random();this.vector = {x: this.speed * Math.cos(this.angle),y: this.speed * Math.sin(this.angle),} this.element = new Circle({shape: {cx: this.x,cy: this.y,r: this.radius,},style: {fill: this.color,}});
};

更新位置坐标方法:

updatePosition(){//边界判断if(this.x >= winW || this.x <= 0){this.vector.x *= -1;}if(this.y >= winH || this.y <= 0){this.vector.y *= -1;}if(this.x > winW){this.x = winW;}if(this.x < 0){this.x = 0;}if(this.y > winH){this.y = winH;}if(this.y < 0){this.y = 0;}//更新位置坐标this.x += this.vector.x;this.y += this.vector.y;//更新形状坐标this.element.shape.cx = this.x;this.element.shape.cy = this.y;this.element.dirty();
};

划线方法:

drawLines(){//清空lines,用于重绘线for(let i = 0; i < this.lines.length; i ++){let l = this.lines[i];zr.remove(l); //删除形状l = null; //并解除绑定}this.lines = []; //删除后,清空数组//遍历各个点之间的距离for(let i = 0; i < particals.length; i ++){let p = particals[i];//勾股定理,获取两点之间的距离let distance = Math.sqrt(Math.pow(this.x - p.x, 2) + Math.pow(this.y - p.y, 2));if(distance <= opts.joinLineDis && distance > 0){let opacity = 1 - distance / opts.joinLineDis; //根据距离大小来设置透明度let color = opts.lineColor.match(/\d+/g); //因为这里要用到透明度,所以需要重新组合rgba,先把各个颜色值取到数组中let l = new Line({shape: {x1: this.x,y1: this.y,x2: p.x,y2: p.y,},style: {stroke: 'rgba(' + color[0] + ',' + color[1] + ',' + color[2] + ',' + opacity + ')', //组建颜色fill: null},});this.lines.push(l); //存入lineszr.add(l); //加入ZRender Storage中}};
}

目前所有核心部分已完成,现在来初始化它:


var init = function(){for (let i = 0; i < opts.particalAmount; i++) {let p = new Partical();particals.push(p); // 把粒子实例 存入particals中,方便后面操作zr.add(p.element); //加入 ZRender Storage中}
};

效果:



开始动画函数,让粒子动起来,并生成连接线:

function loop(){for(let i = 0; i < particals.length; i ++){let p = particals[i];p.updatePosition(); //更新位置p.drawLines(); //绘制线段}window.requestAnimationFrame(loop);
};

最终效果:


全部代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Document</title><script src="./esl.js"></script><style>#main{position: absolute;left:0;top:0;background: #000;z-index: -1;}</style>
</head>
<body><canvas id="main"></canvas><script>require.config({packages:[{name: 'zrender',location: './src',main: 'zrender',},],
});require(['zrender','zrender/graphic/shape/Circle','zrender/graphic/shape/Line'], function(zrender, Circle, Line){/** 作者:王乐平* 博客:http://blog.csdn.net/lecepin/*///-----全局var-----{var winH = window.innerHeight;var winW = window.innerWidth;var opts = {background: '#000', //Canvas背景色paricalRadius: 2,paricalColor: 'rgb(0, 255, 0)',lineColor: 'rgb(0, 255, 0)',joinLineDis: 300,particalAmount: 30,speed: 1,};var tid; //setTimeout id,防抖处理var particals = []; //用于存储partical对象//-----------------}var zr = zrender.init(main, {width: winW, height: winH});zr.dom.style.backgroundColor = opts.background;window.addEventListener('resize', function(){clearTimeout(tid);var tid = setTimeout(function(){winW = zr.dom.width = window.innerWidth;winH = zr.dom.height = window.innerHeight;zr.refresh();}, 300); //这里设置了300ms的防抖间隔}, false);class Partical {constructor(){this.lines = [], //用于存储连线//粒子坐标初始化this.x = winW * Math.random();this.y = winH * Math.random();this.speed = opts.speed + Math.random(); //这个random可不加,主要是为了制作不同的速度的this.angle = ~~(360 * Math.random());this.color = opts.paricalColor;this.radius = opts.paricalRadius + Math.random();this.vector = {x: this.speed * Math.cos(this.angle),y: this.speed * Math.sin(this.angle),} this.element = new Circle({shape: {cx: this.x,cy: this.y,r: this.radius,},style: {fill: this.color,}});};updatePosition(){if(this.x >= winW || this.x <= 0){this.vector.x *= -1;}if(this.y >= winH || this.y <= 0){this.vector.y *= -1;}if(this.x > winW){this.x = winW;}if(this.x < 0){this.x = 0;}if(this.y > winH){this.y = winH;}if(this.y < 0){this.y = 0;}this.x += this.vector.x;this.y += this.vector.y;this.element.shape.cx = this.x;this.element.shape.cy = this.y;this.element.dirty();};drawLines(){//清空linesfor(let i = 0; i < this.lines.length; i ++){let l = this.lines[i];zr.remove(l);l = null;}this.lines = [];//遍历各个点之间的距离for(let i = 0; i < particals.length; i ++){let p = particals[i];//勾股定理let distance = Math.sqrt(Math.pow(this.x - p.x, 2) + Math.pow(this.y - p.y, 2));if(distance <= opts.joinLineDis && distance > 0){let opacity = 1 - distance / opts.joinLineDis;let color = opts.lineColor.match(/\d+/g);let l = new Line({shape: {x1: this.x,y1: this.y,x2: p.x,y2: p.y,},style: {stroke: 'rgba(' + color[0] + ',' + color[1] + ',' + color[2] + ',' + opacity + ')',fill: null},});this.lines.push(l);zr.add(l);}};}}var init = function(){for (let i = 0; i < opts.particalAmount; i++) {let p = new Partical();particals.push(p);zr.add(p.element);}};function loop(){for(let i = 0; i < particals.length; i ++){let p = particals[i];p.updatePosition();p.drawLines();}window.requestAnimationFrame(loop);};init();loop();});
</script>
</body>
</html>

博客名称:王乐平博客

CSDN博客地址:http://blog.csdn.net/lecepin

知识共享许可协议
本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/401666.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python模块学习(1)

模块让你能够有逻辑地组织你的Python代码段。把相关的代码分配到一个 模块里能让你的代码更好用&#xff0c;更易懂。模块也是Python对象&#xff0c;具有随机的名字属性用来绑定或引用。简单地说&#xff0c;模块就是一个保存了Python代码的文件。模块能定义函数&#xff0c;类…

MySQL 迁移到半同步模式

下面实验是基于http://5073392.blog.51cto.com/5063392/1536487搭建的1&#xff09; 在master上安装插件mysql> install plugin rpl_semi_sync_master SONAME semisync_master.so;Query OK, 0 rows affected (0.18 sec)2&#xff09;在salve上安装插件mysql> INSTALL PLU…

CSS动画实战:创建一个太极Loading图

这里主要是使用CSS的animation和伪类来构建&#xff0c;分析设定关键帧的执行顺序和时间段。 效果 动画分析 首先通过效果对动画执行进行一下分析&#xff1a; 边框的四条边进行按顺序动画加载 。矩形边框变为圆行边框。太极图内部图案渐渐出现。太极图旋转。整个动画逆序执…

PWA(Progressive Web App)入门系列:(二)相关准备

前言 在上一章中&#xff0c;对PWA的相关概念做了基本介绍&#xff0c;了解了PWA的组成及优势。为了能够更快的进入PWA的世界&#xff0c;这一章主要对在PWA开发中&#xff0c;需要注意的问题&#xff0c;运行的环境及调试工具做介绍说明。 浏览器要求 因为目前各浏览器对于…

error: Refusing toundefine while domain managed save image exists

虚拟机无法删除的处理方法1&#xff09;、查看虚拟机状态virsh # list --allId Name State----------------------------------------------------9 instance-000000c7 running10 instance-0000002e running11 inst…

PWA(Progressive Web App)入门系列:(三)PWA关键技术Manifest

前言 前面说过&#xff0c;让Web App能够达到Native App外观体验的主要实现技术就是PWA中的manifest技术&#xff0c;本章会详细说明manifest的实现&#xff0c;及各个参数的具体含义&#xff0c;还将了解如何定义Web App的启动图标、启动样式等。 简介 manifest是一种简单的…

利用百度LBS做一个小Demo

为什么80%的码农都做不了架构师&#xff1f;>>> 申请ak&#xff08;即获取密钥&#xff09;http://lbsyun.baidu.com/apiconsole/key?applicationkey 去这儿注册一个开发者账号即可拼写发送http请求的url譬如这样的调用http://api.map.baidu.com/geocoder/v2/?ad…

PWA(Progressive Web App)入门系列:(四)Promise

前言 这一章说一下ES6的Promise对象。为什么要在PWA系列的文章中讲Promise呢&#xff1f;因为PWA中的许多技术API中都是以Promise返回的方式返回的&#xff0c;为了对后续章节中PWA技术API更好的理解&#xff0c;这里就来说一个Promise对象。 Promise出现的背景 在JavaScrip…

图文详解如何搭建Windows的Android C++开发环境

原地址:http://www.apkbus.com/android-18595-1-1.html ////TITLE:// 图文详解如何搭建Windows的Android C开发环境&#xff08;一&#xff09;//AUTHOR:// norains//DATE:// Thursday 14-April-2011//Environment:// Cygwin 1.7.9// Android NDK r5//1. 下载A…

PWA(Progressive Web App)入门系列:(五)Web Worker

前言 在说Service Worker前有必要说一下Web Worker&#xff0c;因为Service Worker本身就属于Web Worker的延伸&#xff0c;大部分功能也是基于Web Worker进行的扩展。 背景 众所周知&#xff0c;JavaScript引擎是以单线程调度的方式进行&#xff0c;我们无法同时运行多个Ja…

Glob Patterns匹配模式使用

前段时间在用workbox时&#xff0c;在做precache时&#xff0c;匹配模式基于的是Glob Pattern模式&#xff0c;于是就看了下相关文档。 下面翻译一下node-glob的使用&#xff0c;原文&#xff1a;https://github.com/isaacs/node-glob#glob-primer Glob 像在shell里面&#x…

vSphere5.5安装教程

vSphere5.5安装教程 首先&#xff0c;下载OVF模版 http://pan.baidu.com/s/1o6kaEs6 点击文件下--部署OVF模版 把刚才下载下来的文件放到浏览里面&#xff0c;下一步 下一步 给vmware vcenter Server命名 这里选择Thin Provision精简置备 检查设置&#xff0c;完成 安装部署中……

Workbox CLI v3.x 中文版

在写PWA应用时&#xff0c;用到WorkBox工具&#xff0c;使用过程中发现没有中文的帮助文档&#xff0c;为了体验好一些&#xff0c;也为了方便自己和他人查看&#xff0c;在这里翻译了一下workbox-cli。 Workbox CLI 是什么? Workbox命令行&#xff08;在workbox-cli包内&…

Workbox.routing v3.x 中文版

NAMESPACE STATIC VERSION V3.6.1 类 NavigationRoute NavigationRoute可以轻松创建匹配浏览器navigation requests的Route。 它仅匹配mode设置为navigate的请求。 您可以只使用blacklist和whitelist参数中的一个或两个&#xff0c;将此路由应用于导航请求中。 RegExpRout…

安装wps导致 application/kset 上传文件类型报错解决办法

电脑中安装wps上传execl时&#xff0c;上传.xls文件时 报错 application/kset 文件类型不正确打印array()print_r($_FILES ) 结果如下&#xff1a;Array ( [userfile] > Array ( [name] > Template.xls[type] > application/kset[tmp_name] > C:\\Windows\\temp\\p…

Workbox.strategies v3.x 中文版

NAMESPACE STATIC VERSION V3.6.1 该模块提供了大多数serviceworker常用的缓存策略的简单实现。 类 CacheFirst cache-first请求策略的实现。 缓存优先策略对于带版本号的资源是非常有用的&#xff0c;像这种URLstyles/example.a8f5f1.css&#xff0c;因为它们可以长时间缓存…

集算器访问HTTP数据的代码示例

使用集算器&#xff08;esProc&#xff09;可以很方便的从http数据源读取数据进行处理。本例子中有一个servlet&#xff0c;对外提供json格式的雇员信息查询。Servlet访问数据库的员工表&#xff0c;保存了员工的信息&#xff0c;如下&#xff1a;EID NAME SURNAME …

PWA(Progressive Web App)入门系列:Cache Storage Cache

前言 目前浏览器的存储机制有很多&#xff0c;如&#xff1a;indexedDB、localStorage、sessionStorage、File System API、applicationCache 等等&#xff0c;那为什么又制定了一套 Cache API 呢&#xff1f;对比其他存储机制有什么优势&#xff1f; 简介 Cache API 是一套…

oracle11g AUD$维护

http://blog.csdn.net/lwei_998/article/details/7394638SYSTEM表空间使用率达到了85%,查出是用来记录审计记录的aud$表占用了很大的空间。备份后truncate掉AUD$,问题临时解决。记得oracle11.2可以把aud$迁移到普通的表空间。于是试了一把&#xff0c;果然ok。1.检查SYSTEM表空…