這是在上篇隨筆的第三種方法下進行改進的。
上篇說到的方法是在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
最后在這里說兩句,這些都是我在網上一點點拼湊,一點點磨出來的,找到別人寫的,基本都是沒注釋的,因為不知道他的思想,看他的代碼也是有些費勁。這里我寫注釋也不是為了讓別人看着方便,是為了讓自己以后能看懂,以前寫代碼,我基本是很少注釋的,自認為自己的結構很明確在這,不需要注釋。后來慢慢的就發現注釋還是很重要的。我寫這些東西,是因為我發現,想學好一樣新的東西,就要學着把它完整的介紹給下一個一點都不懂的人聽,並能夠讓他很好的學會,這樣才算自己也學好了,好吧,這個貌似我還沒學好。好的,我說完了。聚合,離散的效果,點擊屏幕就能看到,也懶得寫按鈕了