canvas元素標籤強大之處在於能夠直接在HTML上進行圖形操做,具備極大的應用價值。
canvas 能夠實現對圖像的像素操做,這就要說到 getImageData() 方法了。html
CanvasRenderingContext2D.getImageData()
返回一個 ImageData 對象,用來描述 canvas 區域隱含的像素數據,這個區域經過矩形表示,起始點爲(sx, sy)、寬爲sw、高爲sh。前端
ctx.getImageData(sx, sy, sw, sh);
git
sx
:將要被提取的圖像數據矩形區域的左上角 x 座標。github
sy
:將要被提取的圖像數據矩形區域的左上角 y 座標。面試
sw
:將要被提取的圖像數據矩形區域的寬度。算法
sh
:將要被提取的圖像數據矩形區域的高度。canvas
一個 ImageData 對象,包含 canvas 給定的矩形圖像數據。segmentfault
ImageData 對象會有三個屬性,height
、width
和 data
。跨域
ImageData.height
使用像素描述 ImageData 的實際高度,這個值其實等於 getImageData() 方法中的參數 sh
數組
ImageData.width
使用像素描述 ImageData 的實際寬度。這個值其實等於 getImageData() 方法中的參數 sw
ImageData.data
一個一維數組,包含以 RGBA 順序的數據,數據使用 0 至 255(包含)的整數表示。
若是高度(sh)或者寬度(sw)變量爲0,則會拋出錯誤。
以上是須要知道的基本知識,下來看幾個例子吧!
效果圖
實現思路
一、先把圖片畫到 canvas 上,
二、獲取鼠標移動時的座標並經過 getImageData() 方法,獲取這一個點的像素,
三、獲得像素信息後,拼接出 rgba
的字符串,再設置下面的小正方形的背景是這個顏色。
代碼請點這裏
效果圖
實現思路
一、先在 canvas 上畫出圖片,
二、經過 getImageData() 方法,獲取整個 canvas 上的像素信息,
三、點擊按鈕時,遍歷獲取到的像素信息的每一個像素的 紅色值、綠色值 和 藍色值,相加求出平均值,再把平均值賦值給紅色、綠色和藍色,這麼作是爲了求出每一個像素的灰度,
四、而後把改變後的像素信息,經過 putImageData() 方法從新添加到 canvas中,就實現了圖片灰度的效果。
代碼請點這裏
除了圖片能夠實現灰度的效果外,由於 canvas 中也能夠放視頻,對於視頻也能夠實現灰度的效果,原理都是同樣的,操做其實也同樣,其實視頻作灰度效果,能夠理解爲給不少張圖片作灰度效果。
效果圖
代碼請點這裏
效果圖
實現思路
咱們先不說,怎麼實現最後的動畫效果,咱們先來想怎麼獲取文字全部像素在 canvas 上的座標,
一、先獲取文字在canvas上的像素信息
計算機的速度是很快的,因此用戶是看不到紅色文字的,若是你以爲這種方式很差,也能夠在用一個 canvas 專門來獲取文字像素,這個canvas 不要讓用戶看到就行了。
咱們知道文字的像素信息,知道每一個像素的座標,就能實現各類效果,像示例中的效果,僅僅只是改變一個 x 座標的值而已。
二、遍歷保存文字像素的數組(dotList),每一個像素(Dot)對象還有一個 nowX 屬性,初始值是0,每次畫最後的圓點的時候,都是用這個屬性做爲圓的 x 座標,nowX 屬性不斷的增長,直到最後等於像素(Dot)對象的 x 屬性值就中止。
代碼請點這裏
這種效果我也是在 Canvas基礎-粒子動畫Part3 這篇文章中看到的,做者寫的很好,推薦看看。
在github上也有一個不錯的項目 shape-shifter,能夠了解一下。
問題
平面上有若干個不特定的形狀,以下圖所示。請寫程序求出物體的個數,以及每一個不一樣物體的面積。
效果圖
實現思路
一、建立存儲圖片像素點的二維數組(coordinates ),圖中只有兩種顏色,空白區域一種顏色,形狀區域一種顏色,空白區域的像素標記爲0,形狀區域標記爲1,相似下面這樣
0,0,0,0,0,0,0,0,0,0,0,0 0,0,1,1,1,0,0,0,0,0,0,0 0,1,1,1,1,0,0,0,0,0,0,0 0,1,1,1,0,0,0,1,1,1,1,0 0,0,0,0,0,0,1,1,1,0,0,0 0,0,0,0,0,0,1,1,1,0,0,0 0,0,0,0,0,0,0,0,0,0,0,0
二、計算有多少個形狀,就是看二維數組中有多少個連續爲1的塊,計算形狀的面積,就是算一個連續爲1的塊,有多少個1。
這就要經過 遞歸回溯算法 來計算了。
回溯算法實際上一個相似枚舉的搜索嘗試過程,主要是在搜索嘗試過程當中尋找問題的解,當發現已不知足求解條件時,就「回溯」返回,嘗試別的路徑。
回溯法是一種選優搜索法,按選優條件向前搜索,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步從新選擇,這種走不通就退回再走的技術爲回溯法。
代碼請點這裏
這裏有一個示例,展現下用回溯法怎麼找到這些形狀的。
這個例子出自 前端面試的一道算法題(使用canvas解答)這篇文章,文章講的也很好,推薦看看
用 getImageData() 方法 要考慮兩個問題
一、跨域問題
getImageData() 方法不容許操做非此域名外的圖片資源,因此若是想本地試試文章中的例子,直接寫圖片路徑就會報錯,
不過能夠將圖片轉換成base64編碼,直接把base64編碼賦值給圖片的src屬性就能夠簡單的解決這個問題了。這種方式僅僅適用於圖片,若是是視頻的話,仍是須要服務器端的配合。
具體能夠看看這篇文章 解決canvas圖片getImageData,toDataURL跨域問題
二、性能問題
getImageData() 方法通常獲取的像素信息是不少的,因此這就要考慮性能的問題,至於怎麼優化也是要看具體場景了,好比在文中的文字粒子效果的示例中,能夠先用 measureText() 方法計算文字寬度,結合 fontSize 就能知道 文字在哪塊區域,只經過這個塊區域獲取文字的像素就行了。
getImageData() 方法,一句話總結就是獲取 canvas 上的像素信息,文中實現的各類效果不論是簡單的仍是複雜的,都是在操做像素。
經過getImageData() 方法,能作的事情還有不少,遠不止文章中提到的這些,好比實現其餘的濾鏡效果,文中只是說了一個灰度,咱們還能夠去實現反相,模糊,浮雕等,文中實現了文字粒子效果,其實圖片也能夠實現粒子效果,除此以外還有不少好玩的事情,可是本人才疏學淺,好多我也不知道。
最後,若是文中有不足或者錯誤的地方,還請小夥伴們指出,萬分感謝。
Canvas基礎-粒子動畫Part3
前端面試的一道算法題(使用canvas解答)
leetcode題解(遞歸和回溯法)