利用纯JS实现像素逐渐显示的方法示例
前言
对于新手的我,以前从来没有做过对像素进行操作的实例。于是把资料书找了出来,实现了这个功能,比较简单,大神勿喷。下面是效果图,因为重在思路,效果就简陋一些。
实现思路
其实就是简单的用js实现将左上角的矩形随时间图像逐渐显示在它的右下方。
首先,先把思路架构起来,因为对像素操作,所以需要用到canvas。
然后,我们 需要画一个矩形,并且需要获取到它的每一个像素的值,即每一个像素的4要素,rgba。(方法getimagedata,4个参数,前两个坐标,x和y,后两个是长和宽)
最后,用一个定时器实现逐渐显示的功能。(显示可以用putimagedata,3个参数,第一个是需要显示的图像,第二和第三是坐标值xy)
然后我们开始动手敲代码:
我们可以先做出一个没有定时器的,也就是先试着获取到原矩形1/10的像素点,然后显示出来。
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <style> body{ background-color: black; } canvas{ background-color: white; } </style> <title>title</title> <script> window.onload = function(){ var oc = document.queryselector("#c"); var ogc = oc.getcontext("2d"); ogc.fillrect(0,0,100,100);//画原矩形 var rectdata = ogc.getimagedata(0,0,100,100);//获取原矩形的像素点的值 var w = rectdata.width;//原矩形的宽 var h = rectdata.height;//原矩形的长 var datac = randomdata(w*h,w*h/10);//randomdata方法实现随机从原矩形的像素点中抽取一部分出来 var newdata = ogc.createimagedata(w,h);//创造一个新的矩形 //datac数组中存放的是第几个像素,*4是为了把图片的data数组定位到这个像素的数据的第一个值,然后加一是第二个,以此类推。 for(var j=0;j<datac.length;j++){ newdata.data[4*datac[j]]=rectdata.data[4*datac[j]]; newdata.data[4*datac[j]+1]=rectdata.data[4*datac[j]+1]; newdata.data[4*datac[j]+2]=rectdata.data[4*datac[j]+2]; newdata.data[4*datac[j]+3]=rectdata.data[4*datac[j]+3]; } ogc.putimagedata(newdata,w,h); function randomdata(allnum,nownum) { var dataa = []; var datab = []; for(var i=0;i<allnum;i++){ dataa.push(i); } for(var i=0;i<nownum;i++){ datab.push(dataa.splice(math.floor(math.random()*dataa.length),1)); } return datab; } } </script> </head> <body> <canvas id="c" width="400" height="400"></canvas> </body> </html>
其中因为getimagedata的data属性是一个数组,而且数组中的存放的东西,就是我们需要的rgba4个数,存放形式为:
- data[0]第一个像素点的r值:
- data[1]:第一个像素点的g值
- data[2]:第一个像素点的b值
- data[3]:第一个像素点的a值
- data[4]:第二个像素点的r值
- data[5]:第二个像素点的g值
以此类推,4个一循环。
然后数组datac里面存放的是取出的像素点位置,然后用乘以4和分别加一,加二,加三为了定位到每一个像素点的rgba分别的4个值。此时就能实现抽取一部分像素点显示的功能。
最后,将代码改进。
第一步,我们需要改进randomdata这个函数,使之返回的数组是包含原矩形的所有像素。
function randomdata(allnum,nownum) { var dataa = []; var datab = []; for(var i=0;i<allnum;i++){ dataa.push(i); } for(var i=0;i<allnum/nownum;i++){ var otherdata = []; for(var j=0;j<nownum;j++){ otherdata.push(dataa.splice(math.floor(math.random()*dataa.length),1)); } datab.push(otherdata); } return datab; }
嵌套了一层for循环,使返回的datab数组里面分成了一定组数的一定量个像素点。
然后增加一个定时器,最终代码为:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <style> body{ background-color: black; } canvas{ background: #fff; } </style> <title>title</title> <script> window.onload = function(){ var oc = document.queryselector("#c"); var ogc = oc.getcontext("2d"); ogc.fillrect(0,0,100,100); var rectdata = ogc.getimagedata(0,0,100,100); var w = rectdata.width; var h = rectdata.height; var datac = randomdata(w*h,w*h/10); var newdata = ogc.createimagedata(w,h); var inum = 0; var timer = setinterval(function () { for(var j=0;j<datac[inum].length;j++){ newdata.data[4*datac[inum][j]]=rectdata.data[4*datac[inum][j]]; newdata.data[4*datac[inum][j]+1]=rectdata.data[4*datac[inum][j]+1]; newdata.data[4*datac[inum][j]+2]=rectdata.data[4*datac[inum][j]+2]; newdata.data[4*datac[inum][j]+3]=rectdata.data[4*datac[inum][j]+3]; } ogc.putimagedata(newdata,w,h); if(inum<9){ inum++; } else{ inum=0; ogc.clearrect(w,h,w,h); for(var i=0;i<newdata.data.length;i++){ newdata.data[i]=0; } } },200); function randomdata(allnum,nownum) { var dataa = []; var datab = []; for(var i=0;i<allnum;i++){ dataa.push(i); } for(var i=0;i<allnum/nownum;i++){ var otherdata = []; for(var j=0;j<nownum;j++){ otherdata.push(dataa.splice(math.floor(math.random()*dataa.length),1)); } datab.push(otherdata); } return datab; } } </script> </head> <body> <canvas id="c" width="400" height="400"></canvas> </body> </html>
其中31到35行的for循环还是一样将原矩形的像素点传递给新矩形。但是这一次是用inum来实现分批次的传递和显示。注意这里的datac,也就是randomdata函数返回的数组是一个二维数组。最后用一个if—else判断来控制计时器的继续计时和停止计时。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。