利用純JS實(shí)現(xiàn)像素逐漸顯示的方法示例
前言
對于新手的我,以前從來沒有做過對像素進(jìn)行操作的實(shí)例。于是把資料書找了出來,實(shí)現(xiàn)了這個功能,比較簡單,大神勿噴。下面是效果圖,因?yàn)橹卦谒悸罚Ч秃喡恍?/p>



實(shí)現(xiàn)思路
其實(shí)就是簡單的用JS實(shí)現(xiàn)將左上角的矩形隨時間圖像逐漸顯示在它的右下方。
首先,先把思路架構(gòu)起來,因?yàn)閷ο袼夭僮?,所以需要用到canvas。
然后,我們 需要畫一個矩形,并且需要獲取到它的每一個像素的值,即每一個像素的4要素,rgba。(方法getImageData,4個參數(shù),前兩個坐標(biāo),X和Y,后兩個是長和寬)
最后,用一個定時器實(shí)現(xiàn)逐漸顯示的功能。(顯示可以用putImageData,3個參數(shù),第一個是需要顯示的圖像,第二和第三是坐標(biāo)值XY)
然后我們開始動手敲代碼:
我們可以先做出一個沒有定時器的,也就是先試著獲取到原矩形1/10的像素點(diǎn),然后顯示出來。
<!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);//獲取原矩形的像素點(diǎn)的值
var w = rectData.width;//原矩形的寬
var h = rectData.height;//原矩形的長
var dataC = randomData(w*h,w*h/10);//randomData方法實(shí)現(xiàn)隨機(jī)從原矩形的像素點(diǎ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>
其中因?yàn)間etImageData的data屬性是一個數(shù)組,而且數(shù)組中的存放的東西,就是我們需要的rgba4個數(shù),存放形式為:
- data[0]第一個像素點(diǎn)的r值:
- data[1]:第一個像素點(diǎn)的g值
- data[2]:第一個像素點(diǎn)的b值
- data[3]:第一個像素點(diǎn)的a值
- data[4]:第二個像素點(diǎn)的r值
- data[5]:第二個像素點(diǎn)的g值
以此類推,4個一循環(huán)。
然后數(shù)組dataC里面存放的是取出的像素點(diǎn)位置,然后用乘以4和分別加一,加二,加三為了定位到每一個像素點(diǎn)的rgba分別的4個值。此時就能實(shí)現(xiàn)抽取一部分像素點(diǎn)顯示的功能。

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

