ZRender实现粒子网格动画实战
生活随笔
收集整理的這篇文章主要介紹了
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部分
這里主要用到的形狀就是Circle和Line,先引入這兩個組件:
['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实现粒子网格动画实战的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华硕 RT-AC54U路由器固件功能说明
- 下一篇: ColorUI 使用文档