试想一下,一张图片怎样取得每个像素点,在每个像素点上绘制一个粒子(圆)呢?或者说记录上每个像素点的位置?-----canvas提供了一种方法getImageData,我们来假设一个场景,首先是一张800X600的canvas画布,这张画布默认是白色的背景图,然后有一张600X400的png图片;那么首先的代码就应该是:
var canvas=document.getElementById("myCanvas");//获取canvas画布
var ctx=canvas.getContext("2d");//声明这个画布是2d
ctx.clearRect(0,0,canvas.width,canvas.height);//绘制之前先清空画布
var image = new Image();
image.src='201702081110069.png';//创建一张图片,并声明路径
现在的图片已经放上去了,但是还没有加载出来,更没有绘制到画布上,所以接下来就是要先让图片加载完成,然后绘制到画布上:
var imgData = null;
image.onload = function(){//在图片加载完成后
ctx.drawImage(image,0,0,400,400);//将图片绘制到画布上
imgData=ctx.getImageData(0,0,400,400); //获取图表像素信息
}
关键代码来了,getImageData里面就存储了我们需要的信息,那么我们就遍历这张图片的宽(600)和高(400),我们就能拿到整张图片的每个像素点,那么,透明部分我们就过滤掉!
var pos=0;
var data=imgData.data; //RGBA的一维数组数据
var nowNum=0;
for(var i=1;i<=imgData.height;i++){
for(var j=1;j<=imgData.width;j++){//遍历宽高
pos=(i-1)*imgData.width+(j-1); //取得像素位置
if(data[pos*4]>0){//开始过滤
var onePix= new Yuan(100,j,i);//创建一个圆,并把现在的宽高像素传递过去
copyPixels.push(onePix);//把创建好的圆放进一个数组里面
}
}
}
//下面是圆的构造函数
function Yuan(distance,j=rd(50,400),i=rd(50,400)){
this.x = j; //当前J就是X轴的坐标, --->绘制时的实时位置
this.y = i;//当前的i就是Y轴的坐标
this.targetX = 0;//将要去的粒子位置
this.targetY = 0;
this.color = '#bbb';//定义粒子的颜色(其实在上面的遍历是可以拿到本身的颜色的,偷懒)
}
当然,这只是阐述了方法,授人以鱼不如授人以渔.但是,相信很多同僚都是过来直接找代码赋值粘贴的,所以还是不多说了,上代码吧,如果有用,浪费你一秒钟帮我点个赞^_^!
var pixels=[]; //存储第一张图片的粒子对象
var copyPixels = [];//储存第一张图片的粒子对象
var otherPixs = [];//存放了第二张图片的粒子对象
// 粒子的构造函数
function Yuan(distance,j=rd(50,400),i=rd(50,400)){
this.x = j; //当前J就是X轴的坐标, --->绘制时的实时位置
this.y = i;//当前的i就是Y轴的坐标
this.targetX = 0;
this.targetY = 0;
}
//绘制方法
function drawPic(pixels){
var canvas=document.getElementById("myCanvas");
var ctx=canvas.getContext("2d");
ctx.clearRect(0,0,canvas.width,canvas.height);//清除上一帧
var len=pixels.length,curr_pixel=null;
for(var i=0;i<len;i+=5){//相隔4个像素点画一个圆,减少粒子的生成
curr_pixel=pixels[i];
// ctx.fillStyle=curr_pixel.color;
// ctx.fillRect(curr_pixel.x,curr_pixel.y,1,1);//第一种画圆方式
ctx.beginPath();//第二种画圆方式
ctx.strokeStyle = curr_pixel.color;
ctx.arc(curr_pixel.x, curr_pixel.y,2, 0, Math.PI*2);
ctx.fillStyle="curr_pixel.color";//填充颜色,默认是黑色
ctx.fill();//画实心圆
ctx.closePath()
}
}
//图1的绘制取点
function first(){
var canvas=document.getElementById("myCanvas");
var ctx=canvas.getContext("2d");
var image = new Image();
image.src='image1.png';
var imageData;
image.onload=function(){
ctx.drawImage(image,0,0,400,400);//上下要一致
imageData=ctx.getImageData(0,0,400,400); //获取图表像素信息
var pos=0;
var data=imageData.data; //RGBA的一维数组数据
var nowNum=0;
for(var i=1;i<=imageData.height;i++){
for(var j=1;j<=imageData.width;j++){
pos=(i-1)*imageData.width+(j-1); //取得像素位置
if(data[pos*4]>0){
var pixel= new Yuan(500,j+600,i);
pixels.push(pixel);
}
}
}
drawPic(pixels); //绘制图像
};
}
//图形2绘制取点,并把图2的位置赋值给创建好的圆作为目标位置
function second(){
var canvas=document.getElementById("myCanvas");
var ctx=canvas.getContext("2d");
ctx.clearRect(0,0,canvas.width,canvas.height);
var image = new Image();
image.src='image2.png';
var imgData = null;
image.onload = function(){
ctx.drawImage(image,0,0,400,400);
imgData=ctx.getImageData(0,0,400,400); //获取图表像素信息
var pos=0;
var data=imgData.data; //RGBA的一维数组数据
var nowNum=0;
for(var i=1;i<=imgData.height;i++){
for(var j=1;j<=imgData.width;j++){
pos=(i-1)*imgData.width+(j-1); //取得像素位置
if(data[pos*4]>0){
var onePix= new Yuan(100,j,i);
copyPixels.push(onePix);//把第二张图片的信息放入这个数组里面
if(pixels[nowNum]){
pixels[nowNum].targetX =copyPixels[nowNum].x;//把第二张图片的位置赋给粒子对象的目标位置
pixels[nowNum].targetY =copyPixels[nowNum].y;
}else{//第一张图的粒子数量不够,随机添加粒子
var addYuan = new Yuan(100);
addYuan.targetX = copyPixels[nowNum].x;
addYuan.targetY = copyPixels[nowNum].y;
pixels.push(addYuan);
}
nowNum++;
}
}
}
if(pixels.length>copyPixels.length){//如果之前的所生成的粒子太多,让多余的粒子去一个位置
for(var k=0;k<pixels.length;k++){
if(pixels[k].targetX ===0 && pixels[k].targetY ===0){
pixels[k].targetX = pixels[0].targetX ;
pixels[k].targetY = pixels[0].targetY ;
}else{
continue;
}
}
}
}
}
//点取完了,该进行动画了,清除上一帧,绘制下一帧,这就是动画
function animateTo(){
//设置定时器 循环改变X,Y轴数据,然后重新绘制
var num= 0;
secondTimeId = setInterval(()=>{
num= 0;//计数器,记录已经到达目标位置的粒子数量
var leng = pixels.length;
for(var i=0;i<leng;i++){
if(pixels[i].x==pixels[i].targetX && pixels[i].y==pixels[i].targetY){
num++;
continue;
}
if(pixels[i].x<pixels[i].targetX){
pixels[i].x += rd(8,30);//每次刷新运动的随机距离
if(pixels[i].x>pixels[i].targetX){
pixels[i].x=pixels[i].targetX;
}
}else{
pixels[i].x -= rd(8,30);
if(pixels[i].x<pixels[i].targetX){
pixels[i].x=pixels[i].targetX;
}
}
if(pixels[i].y<pixels[i].targetY){
pixels[i].y += rd(1,20);
if(pixels[i].y>pixels[i].targetY){
pixels[i].y=pixels[i].targetY;
}
}else{
pixels[i].y -= rd(1,20);
if(pixels[i].y<pixels[i].targetY){
pixels[i].y=pixels[i].targetY;
}
}
}
//结束掉定时器
if(num == pixels.length){
clearInterval(secondTimeId);
}
drawPic(pixels);
},20)//每一帧刷新时间
}
//随机取整方式
function rd(n,m){
var c = m-n+1;
return Math.floor(Math.random() * c + n);
}
first();//执行第一个方法,页面执行的时候就会绘制出完整的图片
document.getElementById("myCanvas").onclick = function(){//注册点击事件
second();
animateTo();
}
最后,还要再啰嗦的问一句,赞点了吗?^_^