这是在上篇随笔的第三种方法下进行改进的。
上篇说到的方法是在easel.js的框架下写的粒子不规则运动效果。
这是效果图:
现在要做的,就是将这里面运动的粒子聚合在一起,形成一张完整的图像。
这里我会把我实现的整个过程写下来,最后会贴整个代码,基本每行都会加上注释,以便能快速看懂,写的不好的地方希望能理解,以后多多改进。
写这样的效果,原理是很重要的,这其中最重要的就是 getImageData 这个方法。不明白这个方法的,可以去 http://www.w3school.com.cn/tags/canvas_getimagedata.asp 这里看明白后再继续看下文。
getImagedata:function(){ //这里是原生的方法 var c=document.getElementById("canvas"); var ctx=c.getContext("2d"); var img = new Image(); img.src="../img/111.png"; img.onload=function(){ //canvas里面插入图像; ctx.drawImage(img,0,0,page.imgWidth,page.imgHeight); //获取图像每个像素的rgba var imgData=ctx.getImageData(0,0,page.imgWidth,page.imgHeight); //清除插入的图像后执行主函数 ctx.clearRect(0,0,page.imgWidth,page.imgHeight); page.canVas._canvas(); //将透明度大于50的像素点位置存入数组page.dots; //x+=2,y+=2;隔一个像素点取值。 for(var x=0;x<page.imgWidth;x+=2){ for(var y=0;y<=page.imgHeight;y+=2){ var i = (y*imgData.width + x)*4; if(imgData.data[i+3] >= 50){ var dot=[]; dot[0]=x; dot[1]=y; page.dots.push(dot); } } } } }
这段代码的目的,就是获取透明度大于50的像素点,并将他的位置存储起来,以便后面的粒子能够运动到该位置。
写到这里,忽然就不想写了,因为发现我代码里基本都注释好了。算了直接上代码吧,这里上两份完整的代码,第一份是我做的时候用来过度的,我把它保留下来了,第二份是在第一份的基础上,稍微改了几行代码,形成的最终效果。
第一份,用来过度的代码:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>4</title> <meta name="format-detection" content="telephone=no"> <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=0,minimum-scale=1.0,maximum-scale=1.0,minimal-ui" /> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <link rel="stylesheet" href="../css/main.css"/> </head> <body class="hidden re"> <canvas class="ab hide" id="canvascopy"></canvas> <canvas class="ab" id="canvas"></canvas> <script src="../js/zepto.min.1.js"></script> <script src="../js/createjs-2015.11.26.min.js"></script> <script> $(document).ready(function(){ var pageH,pageW; page= { init: function () { ////阻止body滑动 $('body').on("touchmove", function (e) { e.preventDefault(); }); window.addEventListener("touchstart", function (e) { e.preventDefault(); }); $(window).resize(function () { page.resize(); }); //设置粒子生成的图像的宽高 page.imgWidth = 100; page.imgHeight = 100; //存储用来生成图像的粒子的位置 page.dots=[]; page.click=0; //用来存储圆点 page.circleArray=[]; //设置圆点数量 page.circleLength = 2000; page.resize(); page.canVas.init(); }, canVas:{ init:function(){ page.canVas.getImagedata(); //page.canVas._canvas(); //点击屏幕粒子聚合,分散 $("body").on("click",function(){ page.click=!page.click; }) }, _canvas:function(){ stage = new createjs.Stage("canvas"); //循环定义圆点的属性; for(var i= 0;i< page.circleLength;i++){ //随机圆点颜色 var color = "rgba(" + Math.floor(Math.random()*255) + "," + Math.floor(Math.random()*255) + ","+ Math.floor(Math.random()*255) +","+Math.random()+")"; //随机半径 var radius = Math.random()+0.5; //随机初始位置 var x = Math.random()*pageW; var y = Math.random()*pageH; //随机每个点的“移动速度跟方向” var movex = (1-Math.random()*2)*0.5; var movey = (1-Math.random()*2)*0.5; //画点 var particle = page.canVas._drawCircle(color, radius,x,y,movex,movey); //将点存入数组,用于后面调用 page.circleArray.push(particle); //添加形状实例到舞台显示列表 stage.addChild(particle); } //帧率 createjs.Ticker.setFPS(60); //更新阶段将呈现下一帧 createjs.Ticker.addEventListener("tick", page.canVas.tick); }, //圆点函数 _drawCircle:function(color, radius,x,y,movex,movey){ var particle = new createjs.Shape(); particle.graphics.beginFill(color).drawCircle(0, 0, radius); particle.x = x; particle.y = y; particle.movex = movex; particle.movey = movey; return particle; }, //圆点移动 tick:function(){ //粒子游离 if(page.click==0){ page.canVas.animate(0) }else{//粒子聚合成图像 //粒子数大于图像有效像素点数 if(page.dots.length<page.circleLength){ page.canVas.animate2(page.dots.length) page.canVas.animate(page.dots.length) }else{//粒子数小于图像有效像素点数 page.canVas.animate2(page.circleLength) } } //刷新 stage.update(); }, //粒子生成图像的动画; animate2:function(num){ for(var j= 0;j< num;j++){ //图像居中 page.circleArray[j].x-=((page.circleArray[j].x-((page.dots[j][0])+(pageW/2-page.imgWidth/2)))/20); page.circleArray[j].y-=((page.circleArray[j].y-((page.dots[j][1])+(pageH/2-page.imgHeight/2)))/20); } }, //初始动画; animate:function(num){ for(var i= num;i< page.circleLength;i++){ //x轴方向,不同方向,不同速度移动 page.circleArray[i].x+=page.circleArray[i].movex; //超出屏幕,从另一边出来,循环 if(page.circleArray[i].x>=pageW){ page.circleArray[i].x=0 }else if(page.circleArray[i].x<=0){ page.circleArray[i].x=pageW } //Y轴方向,不同方向,不同速度移动 page.circleArray[i].y+=page.circleArray[i].movey; if(page.circleArray[i].y>=pageH){ page.circleArray[i].y=0 }else if(page.circleArray[i].y<=0){ page.circleArray[i].y=pageH } } }, //获取有效像素点位置 getImagedata:function(){ //这里是原生的方法 var c=document.getElementById("canvas"); var ctx=c.getContext("2d"); var img = new Image(); img.src="../img/111.png"; img.onload=function(){ //canvas里面插入图像; ctx.drawImage(img,0,0,page.imgWidth,page.imgHeight); //获取图像每个像素的rgba var imgData=ctx.getImageData(0,0,page.imgWidth,page.imgHeight); //清除插入的图像后执行主函数 ctx.clearRect(0,0,page.imgWidth,page.imgHeight); page.canVas._canvas(); //将透明度大于50的像素点位置存入数组page.dots; //x+=2,y+=2;隔一个像素点取值。 for(var x=0;x<page.imgWidth;x+=2){ for(var y=0;y<=page.imgHeight;y+=2){ var i = (y*imgData.width + x)*4; if(imgData.data[i+3] >= 50){ var dot=[]; dot[0]=x; dot[1]=y; page.dots.push(dot); } } } } } }, resize: function () { pageH = $(window).height(); pageW = $(window).width(); $(".page").width(pageW).height(pageH); $('canvas').attr('width', pageW).attr('height', pageH) } }; page.init(); }); </script> </body> </html>
这里得到的效果是这样的:
这是链接:https://chuyunshi.github.io/Example/chuyunshi-canvas/demo/demo4.html
第二份:这是一份自己想要的效果,等有时间在给他改进改进,做点其他的效果
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>5</title> <meta name="format-detection" content="telephone=no"> <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=0,minimum-scale=1.0,maximum-scale=1.0,minimal-ui" /> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <link rel="stylesheet" href="../css/main.css"/> </head> <body class="hidden re"> <canvas class="ab hide" id="canvascopy"></canvas> <canvas class="ab" id="canvas"></canvas> <script src="../js/zepto.min.1.js"></script> <script src="../js/createjs-2015.11.26.min.js"></script> <script> $(document).ready(function(){ var pageH,pageW; page= { init: function () { ////阻止body滑动 $('body').on("touchmove", function (e) { e.preventDefault(); }); window.addEventListener("touchstart", function (e) { e.preventDefault(); }); $(window).resize(function () { page.resize(); }); //设置粒子生成的图像的宽高 page.imgWidth = 100; page.imgHeight = 100; //存储用来生成图像的粒子的位置 page.dots=[]; page.click=0; //用来存储圆点 page.circleArray=[]; //设置圆点数量 page.circleLength = 0; page.resize(); page.canVas.init(); }, canVas:{ init:function(){ page.canVas.getImagedata(); //page.canVas._canvas(); //点击屏幕粒子聚合,分散 $("body").on("click",function(){ page.click=!page.click; }) }, _canvas:function(){ stage = new createjs.Stage("canvas"); //循环定义圆点的属性; for(var i= 0;i< page.circleLength;i++){ //随机圆点颜色 var color = "rgba(" + page.dots[i][2] + "," + page.dots[i][3] + ","+ page.dots[i][4] +","+page.dots[i][5]+")"; //随机半径 var radius = 1; //随机初始位置 var x = Math.random()*pageW; var y = Math.random()*pageH; //随机每个点的“移动速度跟方向” var movex = (1-Math.random()*2)*0.5; var movey = (1-Math.random()*2)*0.5; //画点 var particle = page.canVas._drawCircle(color, radius,x,y,movex,movey); //将点存入数组,用于后面调用 page.circleArray.push(particle); //添加形状实例到舞台显示列表 stage.addChild(particle); } //帧率 createjs.Ticker.setFPS(60); //更新阶段将呈现下一帧 createjs.Ticker.addEventListener("tick", page.canVas.tick); }, //圆点函数 _drawCircle:function(color, radius,x,y,movex,movey){ var particle = new createjs.Shape(); particle.graphics.beginFill(color).drawCircle(0, 0, radius); particle.x = x; particle.y = y; particle.movex = movex; particle.movey = movey; return particle; }, //圆点移动 tick:function(){ //粒子游离 if(page.click==0){ page.canVas.animate(0) }else{//粒子聚合成图像 //粒子数大于图像有效像素点数 if(page.dots.length<page.circleLength){ page.canVas.animate2(page.dots.length) page.canVas.animate(page.dots.length) }else{//粒子数小于图像有效像素点数 page.canVas.animate2(page.circleLength) } } //刷新 stage.update(); }, //粒子生成图像的动画; animate2:function(num){ for(var j= 0;j< num;j++){ //图像居中 page.circleArray[j].x-=((page.circleArray[j].x-((page.dots[j][0])+(pageW/2-page.imgWidth/2)))/20); page.circleArray[j].y-=((page.circleArray[j].y-((page.dots[j][1])+(pageH/2-page.imgHeight/2)))/20); } }, //初始动画; animate:function(num){ for(var i= num;i< page.circleLength;i++){ //x轴方向,不同方向,不同速度移动 page.circleArray[i].x+=page.circleArray[i].movex; //超出屏幕,从另一边出来,循环 if(page.circleArray[i].x>=pageW){ page.circleArray[i].x=0 }else if(page.circleArray[i].x<=0){ page.circleArray[i].x=pageW } //Y轴方向,不同方向,不同速度移动 page.circleArray[i].y+=page.circleArray[i].movey; if(page.circleArray[i].y>=pageH){ page.circleArray[i].y=0 }else if(page.circleArray[i].y<=0){ page.circleArray[i].y=pageH } } }, //获取有效像素点位置 getImagedata:function(){ //这里是原生的方法 var c=document.getElementById("canvas"); var ctx=c.getContext("2d"); var img = new Image(); img.src="../img/111.png"; img.onload=function(){ //canvas里面插入图像; ctx.drawImage(img,0,0,page.imgWidth,page.imgHeight); //获取图像每个像素的rgba var imgData=ctx.getImageData(0,0,page.imgWidth,page.imgHeight); //清除插入的图像后执行主函数 ctx.clearRect(0,0,page.imgWidth,page.imgHeight); //将透明度大于50的像素点位置存入数组page.dots; //x+=2,y+=2;隔一个像素点取值。 for(var x=0;x<page.imgWidth;x+=2){ for(var y=0;y<=page.imgHeight;y+=2){ var i = (y*imgData.width + x)*4; if(imgData.data[i+3] >= 50){ var dot=[]; dot[0]=x; dot[1]=y; dot[2]=imgData.data[i]; dot[3]=imgData.data[i+1]; dot[4]=imgData.data[i+2]; dot[5]=imgData.data[i+3]; page.dots.push(dot); } } } //将粒子数设置成图像有效像素点数(建议粒子数不要超过2000,数值太大,会卡死) page.circleLength = page.dots.length; page.canVas._canvas(); } } }, resize: function () { pageH = $(window).height(); pageW = $(window).width(); $(".page").width(pageW).height(pageH); $('canvas').attr('width', pageW).attr('height', pageH) } }; page.init(); }); </script> </body> </html>
效果图:
这是链接:https://chuyunshi.github.io/Example/chuyunshi-canvas/demo/demo5.html
以及多写了个链接:https://chuyunshi.github.io/Example/chuyunshi-canvas/demo/demo6.html
不要改demo7.html了。这个是下篇的链接。//修改于2017/6/1/14:54
最后在这里说两句,这些都是我在网上一点点拼凑,一点点磨出来的,找到别人写的,基本都是没注释的,因为不知道他的思想,看他的代码也是有些费劲。这里我写注释也不是为了让别人看着方便,是为了让自己以后能看懂,以前写代码,我基本是很少注释的,自认为自己的结构很明确在这,不需要注释。后来慢慢的就发现注释还是很重要的。我写这些东西,是因为我发现,想学好一样新的东西,就要学着把它完整的介绍给下一个一点都不懂的人听,并能够让他很好的学会,这样才算自己也学好了,好吧,这个貌似我还没学好。好的,我说完了。聚合,离散的效果,点击屏幕就能看到,也懒得写按钮了