Canvas繪制像素風圖片的示例代碼
前言
童年玩紅白機。尤其國內的小霸王那段時光還記得么。
那個馬里奧大叔還記得么。

因為特別喜歡像素風的游戲從小到大一直都是,像素風本身就是由極度簡單的元素構成極度復雜的畫面,因此它可以具備無限的創(chuàng)作空間,形成令人過目不忘的獨特畫風。所以我想借用一張清晰的圖片生成出具有像素點陣的圖片來批量制造。
這是我寫的第一篇短文,很多不足之處請多包涵。
介紹
怎么讓清晰的圖片轉化成像素風格的圖片呢?
首先我們要了解到像素風是由簡單的單一色塊來構成的。

所以我們第一就是上傳一張圖片,然后繪制出來。再解析每隔一定像素給圖片取出色值和位置來。再將這些色值重新繪制到畫布相應位置中,那么一張像素風就是這么簡單實現(xiàn)了。
實現(xiàn)
1. 上傳原圖片
<input type="file" accept=".jpeg,.jpg,.png" />
<script>
document.querySelector("input[type=file]").addEventListener("change",uploadImage, false);
</script>
首先我們先要在頁面放置一個上傳文件得input。這些用accept屬性限制他得上傳類型,因為涉及到常規(guī)的一些圖片上傳這里就傳jpeg,jpg,png三種格式了。
與此同時,要監(jiān)聽他的改變從而拿到所需要轉換的文件。
接下來我將定義一個uploadImage函數(shù)。
function uploadImage(e) {
let file = e.target.files[0];
if (!file) return;
let fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onload = () => {
createImage(fileReader);
e.target.value = "";
document.querySelectorAll("canvas").forEach(node=>{node.remove();})
};
}
function createImage(obj) {
let img = new Image();
img.onload = () => {
drawImage(img);
};
img.src = obj.result;
}
這里我們就可以在fileReader.result拿到上傳后的圖片地址了,再寫一個createImage函數(shù)用來接收文件對象實例化成Image方便給畫布繪制。畢竟一個函數(shù)盡量只做單一的一件事也算是個好習慣吧。
2.繪制原圖片
function drawImage(img) {
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
canvas.width = ctx.width;
canvas.height = ctx.heigh
let w = img.width,
h = img.height;
ctx.drawImage(img,0,0,w,h);
document.body.appendChild(canvas);
}

我們先實現(xiàn)把圖片繪制到畫布上康康,到底啥樣?,F(xiàn)在我們就想了,我們到底要生成多大的像素畫呢。這里我們想做一個全局變量吧。
let width = 32; let height = 32; let size = 10;
我們定義生成一個寬度,高度,像素尺寸。寬高故名思議,就是我們要生成多少寬多少個點,高多少個點的像素。size表示了一個像素填充多大,也就是每隔size個像素取一個色值。
接下來我們改造一下drawImage函數(shù)。
function drawImage(img) {
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
canvas.width = ctx.width = width * size;
canvas.height = ctx.height = height * size;
let w = img.width,
h = img.height;
let v = w / h;
if (v > 1) {
w = width;
h = w / v;
} else {
h = height;
w = h * v;
}
ctx.drawImage(
img,
((width - w) / 2) * size,
((height - h) / 2) * size,
w * size,
h * size
);
document.body.appendChild(canvas);
let pxMap = createPxMap(ctx);
drawPXCanvas(pxMap)
}
我們期望繪制圖片后生成一套個包含像素信息的數(shù)組返回出來,然后我們再進行像素風的生成。
當然我們?yōu)榱藘蓮垐D做對比,把原圖寬高也和像素圖拉平,并且居中顯示在畫布中。
3.繪制像素畫
function createPxMap(ctx){
let pxMap = [];
for (let i = 0; i < width * size; i += size) {
for (let j = 0; j < height * size; j += size) {
let pixel = ctx.getImageData(i, j, 1, 1).data;
let color = `rgba(${pixel[0]},${pixel[1]},${pixel[2]},${pixel[3]/255})`;
pxMap.push({ x: i / size, y: j / size, color });
}
}
return pxMap;
}
我首先要得到點的位置和顏色信息,ctx.getImageData可以獲取到一個buffer數(shù)組,0-3位分別代表紅,綠,藍,透明度的信息。我們要將這些信息存儲起來。
到了最后我們終于要可以繪制像素畫了。
function drawPXCanvas(pxMap) {
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
canvas.width = ctx.width = width * size;
canvas.height = ctx.height = height * size;
pxMap.forEach((px) => {
const { color, x, y } = px;
ctx.fillStyle = color;
ctx.fillRect(x*size, y*size, size, size);
});
document.body.appendChild(canvas);
}
我們要重新生成一個畫布,將剛剛收集到的像素信息逐個繪制到畫布上,這樣一張簡單的像素畫就這么完成了,是不是很容易。

拓展
其實拿到像素信息的時候,可以不局限于canvas2d像素畫了。
還有以下思路:
我們可以借助于css的box-shadow來生成像素畫,用:root 或者scss 更容易控制大小和位置,配合animation生成動畫也未嘗不可。
甚至我們也可以拓展webgl的,生成3d像素,或者其他風格也未嘗不可。
我們可以將再深入分析像素化構成逐幀生成視頻和動畫。。。
到此這篇關于Canvas繪制像素風圖片的示例代碼的文章就介紹到這了,更多相關Canvas 像素風內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持腳本之家!
相關文章
這篇文章主要介紹了Canvas 像素處理之改變透明度的實現(xiàn)代碼的相關資料,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-01-08
本文實現(xiàn)一個類似像素風格的畫板,可以像素小格子可以擦除,框選變色,可以擦出各種圖形,非常具有實用價值,需要的朋友可以參考下2018-11-21
這篇文章主要介紹了canvas像素點操作之視頻綠幕摳圖的相關資料,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-09-11- 這篇文章主要介紹了使用Canvas操作像素的方法的相關資料,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-06-14
HTML5 Canvas畫線技巧——實現(xiàn)繪制一個像素寬的細線
繪制一個像素寬的細線,在使用HTML5 Canvas實現(xiàn)時要特別注意確保你的所有坐標點是整數(shù),否則HTML5會自動實現(xiàn)邊緣反鋸齒,感興趣的朋友可以看下效果圖2013-08-02html5 Canvas畫圖教程(3)—canvas出現(xiàn)1像素線條模糊不清的原因
上次我們講到,canvas有時候會出現(xiàn)1像素的線條模糊不清且好像更寬的情況,這樣的線條顯然不是我們想要的。這篇文章的目的就是弄清楚里面的原理,以及解決它,感興趣的朋友可2013-01-09- 本文通過簡單的代碼實例,以及略猥瑣的圖片demo,展示了canvas在圖像像素數(shù)據(jù)操作方面的常用接口,有需求的朋友可以參考下2012-12-02




