網頁上各類酷炫的粒子動畫看的人眼花繚亂,實際上原理卻很是簡單。javascript
首先咱們須要畫張圖到Canvas上,這裏由於我懶的扣圖(其實是不會),就找了張jpeg的白底圖片。實際上用png的透明圖會好不少。html
必定要等圖片加載完再畫,這很重要,能夠用判斷圖片的complete
屬性和設置onload
方法來等圖片加載完才初始化。
另外繪製圖片是有跨域限制的,本地看的話,要麼你的圖片服務器支持跨域,要麼你就跑個本地服務器吧。java
var img = new Image();
img.src = "images.jpeg";
if(img.complete){
init()
} else {
img.onload = function(){
init()
}
}複製代碼
圖片獲取完以後咱們就能夠開始得到圖片的像素信息了,接口很簡單:git
context.getImageData(x,y,width,height)
得到畫布上指定矩形的像素數據。github
ctx.drawImage(img, sx, sy);
var imgData = ctx.getImageData(sx, sy, imgW, imgH);複製代碼
拿到像素數據,不要太簡單好嗎?! 由於這裏我是把圖片畫在畫布中間的,因此起始點不是(0,0),得到的矩形寬高則爲圖片的寬高。canvas
打印出來看看數據是什麼樣子的。跨域
首先返回的是個ImageData
對象,屬性有data
和width,height,這還不是重點,data的類型是個Uint8ClampedArray
(此處一臉蒙逼), 看起來是個二維數組,數組裏面一堆的數字是什麼鬼(二臉蒙逼)。數組
還好有文檔:服務器
Uint8ClampedArray
對象是一個8位無符號整數的類型化數組,裏面的值都是0-255。實際上,圖像是二維的,是由height決定行數,width決定列像素的行列式。post
作粒子動畫首先須要把圖片粒子化,把位置給找準,這樣出來的東西纔不會是亂七八糟的,因此咱們拿到每一個點的位置信息保存下來就能夠了。
for(var x=0; x<imgData.width; x+=6) {
for(var y=0; y<imgData.height; y+=6) {
var i = (y*imgData.width + x) * 4;
if(imgData.data[i+3] > 128 && imgData.data[i] < 100){
var dot = new Dot(x, y, 2);
dotList.push(dot);
}
}
}複製代碼
兩重循環就不說了,這裏有幾個地方簡單解釋一下:
x+=6
,y+=6
這裏爲何不是1呢?由於是作粒子化,每一個點之間須要有一些空隙纔看的出來,因此不用每一個點都拿,隔一段距離拿一個點就能夠了,這裏的6有點相似於取樣的概念。[i+3]
指的是像素中Alpha的值,大於128是用於過濾掉一些透明像素的。後面那個imgData.data[i] < 100
由於我用的是個白底黑字的jpeg文件,因此還須要把不像黑色的像素過濾掉,由於大都只有黑白兩色,因此就簡單判斷了R值小於100,因此就像以前說的,仍是用png圖片比較好。function Dot(centerX, centerY, radius) {
this.x = centerX;
this.y = centerY;
this.radius = radius;
}複製代碼
最後一步就是把保存下來的信息畫到Canvas上。
function draw(){
var imgW = img.width,
imgH = img.height,
sx = winWidth/2-imgW/2,
sy = winHeight/2-imgH/2;
ctx.clearRect(0, 0, winWidth, winHeight);
ctx.fillStyle = "#000";
for(var i=0; i<dotList.length; i+=1){
curDot = dotList[i];
ctx.save();
ctx.beginPath();
ctx.arc(sx+curDot.x, sy+curDot.y, curDot.radius, 0, 2*Math.PI);
ctx.fill();
ctx.restore();
}
}複製代碼
最後出來的效果:
粒子化基本就寫到這裏,下篇講講用粒子化的東西作動畫吧,最近事情比較多,懶癌又犯了。
源碼地址: github.com/bob-chen/ca…
Part 2 地址:gold.xitu.io/post/57dd27…
Part 3 地址: gold.xitu.io/post/57e7a7…
www.w3school.com.cn/tags/canvas…