我們都知道反鋸齒(anti-aliasing)繪圖給我們帶來更好的視覺體驗,有了這個技術,繪制的圖形的邊緣再不是以前毛毛躁躁的樣子了。這就是采用反鋸齒算法的功勞。其實質就是把要繪制的顏色邊緣和背景顏色做適當的融合,在人的眼睛看來,有種像霧像雨又像風的感覺。HTML5 Canvas的繪圖就是默認anti-aliasing的。其實作為一般的開發者,可以不關心這個東西的存在,好像anti-aliasing是理應如此的。但是,如果我們的用戶非要看到non-anti-aliasing的效果呢?
這個類似有了醬油還要吃鹽的問題。醬油是好,但是有人就是要吃鹽,怎麼辦?
另外的需求是,即使有了醬油,我還是需要吃鹽。為啥,醬油有它的好處,鹽有鹽的用處。
比如:當我們在Canvas上移動鼠標的時候,我需要知道我的鼠標位置在什麼圖形上,即著名的點選問題。Canvas以前的繪圖軟件解決這個問題有標准的方法,就是用圖形的ID作為圖形的顏色值,繪制在內存當中的後台畫布上,當我們移動鼠標在前台顯示的畫布上,我們可以通過獲取後台畫布的該點的像素值(ID)來獲得圖形ID。
這樣一切都近乎完美。後台畫布與前台畫布采用完全一樣的繪圖機制,不同點是前台畫布采用用戶看到的實際像素顏色值,而後台畫布采用圖形的ID作為圖形繪制的像素顏色值。這裡的前提是,我們能控制這些像素值,以確保它在被繪制到後台畫布的時候不被改變,就是我讓你畫一個像素顏色=1,你別自作聰明搞出個=1.5。遺憾的是目前版本的HTML5 Canvas就是這種自作聰明的家伙。迄今為止,我們沒辦法控制去掉anti-aliasing這個自作聰明的算法。我試過即使把context.mozImageSmoothingEnabled=false也不行。
如果這兒誰有一句話的方法可以滿足我上面講的需求,那麼這篇文章直接就等於是狗屎。我費了很多的努力研究出了這篇狗屎文,在這裡以飨讀者,包括我自己。
如何取消(廢止)HTML5 Canvas的反鋸齒功能,在http://stackoverflow.com上也有很多討論。如果讓HTML5實現者來解決這個問題,幾乎就是一句話搞定的事情。然而需要我們一周的時間想各種點子。在HTML5 Canvas本身沒解決這個問題之前,如果讓有的人來解決,幾乎要花掉幾個月的時間,好在如果你看到這篇文章,你就可以告訴你的老板,你只需要幾個晚上就可以解決了。下面我教你具體辦法。
前台畫布我不管它,你怎麼畫是你自己的問題,後台畫布和前台一樣大小,塗滿黑色(#000000)。然後你在前台Canvas上畫圖形id=1的時候,同時在後台畫布上用1為顏色畫這個同樣的圖形。對了,我還沒告訴你如何去掉anti-aliasing,如果不去掉anti-aliasing,系統可能給畫出來的像素顏色是1.5,這顯然不是你想要的,也不是我寫這篇狗屎文的目的。
我只好用代碼來說明問題。記住這是HTML5的代碼,javascript而已。
在HTML5頁面中有Canvas:
<canvas id="_canvasView" width="500" height="400">
This browser does not support HTML5 Canvas.
</canvas>
創建前台畫布:
var canvas = document.getElementById("_canvasView");
var context = canvas.getContext("2d");
創建後台畫布:
var backend = document.createElement("canvas");
backend.width = canvas.width;
backend.height = canvas.height;
var backendContext = backend.getContext("2d");
// 後台畫布塗上黑色(我相信anti-aliasing不會把它搞成灰色)
backendContext.fillStyle = "#000000";
backendContext.fillRect(0, 0, backend.width, backend.height);
// 獲取後台畫布對應的像素數組
var imageObj = backendContext.getImageData( 0, 0, canvas.width, canvas.height);
var imageData = imageObj.data;
如果你想給這個數組裡的像素賦予顏色值,可以像下面的代碼:
function setPixel(imageData, width, height, x, y, red, green, blue)
{
// i 沒做邊界條件檢查,留給讀者自己完成。
var i = (y*width+x)*4;
imageData[i] = red;
imageData[i+1] = green;
imageData[i+2] = blue;
// 下面這個是Alpha,我們不用
//DEL: imageData[i+3]=???;
}
HTML5聲稱imageData是可以直接操控的。因此,這是我們良好的機會去直接設置像素值。把一個像素數組設置回繪圖上下文和我寫累了上廁所拉泡屎一樣簡單:
backendContext.putImageData(imageData, 0, 0);
接下來是發揮你大學學習計算機圖形學的智慧的時候了。