注:本博文代码基于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 国际许可协议进行许可。

ZRender实现粒子网格动画实战相关推荐

  1. canvas动画之二 -- 创建动态粒子网格动画

    最近看到一个粒子网格动画挺炫的,自己也就做了一个,当背景挺不错的.CSDN不能上传超过2M的图片,所以就简单截了一个静态图片: 可以点击这里查看动画. 下面就开始说怎么实现这个效果吧: 首先当然是添加 ...

  2. 粒子群算法实战分享-附原版动画PPT(技术分享也可以文艺范?)

    版权声明:本文为博主原创文章,未经博主允许不得转载. 本文是针对博主使用粒子群优化算法解决水面无人艇静态.动态障碍物规避,及场地布局三类问题,做了更深入的总结分析. 与目前火热的机器学习不同,智能优化 ...

  3. QML动画实战指南:打造华丽且高性能的用户界面动效

    目录标题 引言 QML与Qt Quick简介 动画在现代UI设计中的重要性 QML Animation模块概述 QML动画基础概念 属性动画(PropertyAnimation) 父动画(Parent ...

  4. R语言ggplot2可视化抑制可视化网格中的竖线输出、抑制可视化网格中的横线线输出、抑制背景网格输出实战

    R语言ggplot2可视化抑制可视化网格中的竖线输出.抑制可视化网格中的横线线输出.抑制背景网格输出实战 目录

  5. HTML做3D立体特效,html5 3D立体粒子波浪动画特效代码

    特效描述:html5 3D立体 粒子波浪动画.3D 粒子动画特效 代码结构 1. 引入JS 2. HTML代码 /// Scene const sceneSettings = { width: () ...

  6. 利用Maya进行论文中网格动画数据的渲染

    利用Maya进行论文中网格动画数据的渲染 Maya学习资料 如何利用三维动画制作软件Maya,快速生成高质量的模型渲染效果,从而为论文和Demo增色,比如以下效果: 学习资料下载(91.0M) Sen ...

  7. VTK:网格用法实战

    VTK:网格用法实战 程序输出 程序完整源代码 程序输出 程序完整源代码 // This example shows how to create a rectilinear grid. // #inc ...

  8. VTK:标记网格用法实战

    VTK:标记网格用法实战 程序输出 程序完整源代码 程序输出 程序完整源代码 #include <vtkNew.h> #include <vtkSmartPointer.h>#

  9. VTK:网格上插值网格用法实战

    VTK:网格上插值网格用法实战 程序输出 程序完整源代码 程序输出 程序完整源代码 #include <vtkActor.h> #include <vtkCamera.h> #

最新文章

  1. [END_OBJECT] but found [FIELD_NAME]')
  2. AdaBoostClassifier实战
  3. Git之如何解决sourceTree已经pull全部下来但是本地没有更新的问题
  4. 为什么一流成功人士的闹钟都定在早晨5:57?
  5. Flowable 数据库表结构 ACT_HI_COMMENT
  6. java创建链表成绩管理系统_成绩管理系统 链表版
  7. 内核并发控制---完成量 (来自网易)
  8. bond解除 centos7_centos7上实现bonding
  9. springboot的一些基层原理 2021-05-28
  10. Linux---文件、软链接于硬链接文件
  11. java 单链表是否有环_数据结构与算法随笔之链表-链表是否有环(二)
  12. 玩转VIM编辑器-vim的命令行
  13. 19春招多益网络前端笔试题
  14. 数据结构与算法-第三章 链表
  15. linux sipp 呼叫转移_★★★★盲转接业务的sipp脚本实现
  16. 关于MSXML3.dll与MSXML6.dll
  17. 906. 超级回文数
  18. matlab中时域逐步积分方法,newmark积分法
  19. 服务器重启后samba启动不了,提示stop: Unknown instance: smbd start/running, process 76585
  20. rsa java模数_公钥/私钥中的RSA密钥值和模数

热门文章

  1. find_cmd函数分析
  2. 深入分析Flex [Bindable] (总结)
  3. 美国Palmbeach大学服务器整合改造案例
  4. 餐厅数据分析报告_如何使用数据科学选择理想的餐厅设计场所
  5. 泰坦尼克号 数据分析_第1部分:泰坦尼克号-数据分析基础
  6. php不发送referer,php – 注意:未定义的索引:HTTP_REFERER
  7. 2053. 数组中第 K 个独一无二的字符串
  8. 1436. 旅行终点站
  9. leetcode43. 字符串相乘
  10. 和css3实例教程_最好CSS和CSS3教程