利用純JS實現(xiàn)像素逐漸顯示的方法示例
前言
對于新手的我,以前從來沒有做過對像素進行操作的實例。于是把資料書找了出來,實現(xiàn)了這個功能,比較簡單,大神勿噴。下面是效果圖,因為重在思路,效果就簡陋一些。



實現(xiàn)思路
其實就是簡單的用JS實現(xiàn)將左上角的矩形隨時間圖像逐漸顯示在它的右下方。
首先,先把思路架構起來,因為對像素操作,所以需要用到canvas。
然后,我們 需要畫一個矩形,并且需要獲取到它的每一個像素的值,即每一個像素的4要素,rgba。(方法getImageData,4個參數(shù),前兩個坐標,X和Y,后兩個是長和寬)
最后,用一個定時器實現(xiàn)逐漸顯示的功能。(顯示可以用putImageData,3個參數(shù),第一個是需要顯示的圖像,第二和第三是坐標值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方法實現(xiàn)隨機從原矩形的像素點中抽取一部分出來
var newData = oGc.createImageData(w,h);//創(chuàng)造一個新的矩形
//dataC數(shù)組中存放的是第幾個像素,*4是為了把圖片的data數(shù)組定位到這個像素的數(shù)據(jù)的第一個值,然后加一是第二個,以此類推。
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屬性是一個數(shù)組,而且數(shù)組中的存放的東西,就是我們需要的rgba4個數(shù),存放形式為:
- data[0]第一個像素點的r值:
- data[1]:第一個像素點的g值
- data[2]:第一個像素點的b值
- data[3]:第一個像素點的a值
- data[4]:第二個像素點的r值
- data[5]:第二個像素點的g值
以此類推,4個一循環(huán)。
然后數(shù)組dataC里面存放的是取出的像素點位置,然后用乘以4和分別加一,加二,加三為了定位到每一個像素點的rgba分別的4個值。此時就能實現(xiàn)抽取一部分像素點顯示的功能。

最后,將代碼改進。
第一步,我們需要改進randomData這個函數(shù),使之返回的數(shù)組是包含原矩形的所有像素。
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循環(huán),使返回的dataB數(shù)組里面分成了一定組數(shù)的一定量個像素點。
然后增加一個定時器,最終代碼為:
<!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循環(huán)還是一樣將原矩形的像素點傳遞給新矩形。但是這一次是用iNum來實現(xiàn)分批次的傳遞和顯示。注意這里的dataC,也就是randomData函數(shù)返回的數(shù)組是一個二維數(shù)組。最后用一個if—else判斷來控制計時器的繼續(xù)計時和停止計時。
總結
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關文章
JavaScript Event學習第五章 高級事件注冊模型
在這一章我會講解兩種高級時間注冊模型:W3C和微軟的。因為這兩個方法都不能跨瀏覽器,所以在現(xiàn)在看來他們的使用場合并不多。2010-02-02
JavaScript Cookie 直接瀏覽網(wǎng)站分網(wǎng)址
2009-12-12
詳解釘釘小程序組件之自定義模態(tài)框(彈窗封裝實現(xiàn))
這篇文章主要介紹了釘釘小程序組件之自定義模態(tài)框(彈窗封裝實現(xiàn))的相關知識,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-03-03
Javascript 正則表達式實現(xiàn)為數(shù)字添加千位分隔符
在項目中做貨幣轉(zhuǎn)換的時候經(jīng)常需要可以實現(xiàn)自動格式化輸入的數(shù)字,自動千位分隔符,在網(wǎng)上也看到一些其他網(wǎng)友的實現(xiàn)的代碼,感覺都不是太滿意,于是自己研究了下,分享給大家。2015-03-03
es6中的import導入模塊 和 export導出模塊詳解
require 是 CommonJS 模塊系統(tǒng)中用于導入模塊的關鍵字,采用同步加載方式;而 import 和 export 是 ES6 模塊系統(tǒng)中用于導入和導出模塊的關鍵字,采用靜態(tài)加載方式,并且支持異步加載,這篇文章主要介紹了es6中的import導入模塊 和 export導出模塊,需要的朋友可以參考下2023-11-11

