网页上各类酷炫的粒子动画看的人眼花缭乱,实际上原理却很是简单。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…