基於Canvas實現稿定設計版智能摳圖的擦除畫筆和修補畫筆


先貼下demo地址(備用demo地址)吧,大家可以打開體驗一下,操作說明參考demo源碼(備用源碼地址)中readme介紹。這個功能是好久之前做的一個需求了,是公司產品借鑒😂稿定設計智能摳圖編輯器(舊版)提的需求,由於是比較冷門的功能,所以當時沒找到任何可供參考的方案(近期搜了下好像還是沒有),因此做這個需求那段時間前期壓力還比較大(主要是做之前沒接觸過Canvas API)。而最近剛好在空檔期,就寫篇文章總結下實現思路, 就當做個紀念吧。

1. 實現思路

擦除畫筆和修補畫筆主要基於Canvas API中CanvasRenderingContext2D.globalCompositeOperation這個選項來實現的,理解了核心思路后就會發現具體的實現其實也挺簡單的,而且還可以做一些其它圖像混合相關的功能。當然,用WebGL實現也可以,但是會更麻煩一些,而且性能不見得會更好。

1.1 畫筆實現思路

畫筆是基於鼠標事件監聽器和Canvas API實現的,畫筆的工作流程如下:

  1. 在畫布上觸發mousedown事件時開始調用畫筆進行繪制並綁定/激活mousemove監聽器,每次繪制的圖形都是一個圓形,即填充一個圓弧,填充樣式使用漸變以實現畫筆硬度(詳情參考demo源碼)。
  2. 在畫布上拖動時,即觸發mousemove事件時,連續地繪制畫筆圓點,但是需要基於鼠標事件對象的movementX/movementY進行節流——movementX/movementY中的較大值達到一個閾值才進行繪制, 否則會導致繪制過於頻繁而無法實現畫筆的硬度效果。
  3. 在畫布上觸發mouseup事件時停止繪制並解綁/關閉mousemove監聽器。

1.2 圖像擦除實現思路

圖像擦除——擦除畫筆的核心功能,實際的效果就將圖像上指定區域(由擦除畫筆繪制而來)的像素擦除掉,這個功能其實比較簡單,直接通過globalCompositeOperation中"destination-out"這個選項就能實現。 具體就是在進行繪制之前將ctx.globalCompositeOperation設置為"destination-out",然后再進行繪制,此時繪制的區域中之前繪制的圖像的像素就會被擦除掉。

1.3 圖像修補實現思路

圖像修補——修補畫筆的核心功能,實際的效果就是進行摳圖,也就是將圖像指定區域(由修補畫筆繪制而來)的像素摳出來,這個功能要比圖像擦除麻煩一點,主要是通過globalCompositeOperation中"destination-in"和"source-over"兩個選項來實現,另外,在處理流程中需要額外的隱藏畫布(canvas)去進行一些中間繪制,具體流程如下:

  1. 准備一張隱藏畫布hidden1,將要修補的區域,即畫筆繪制的形狀繪制到hidden1上。
  2. 准備一張隱藏畫布hidden2, 先將其ctx.globalCompositeOperation設置為"source-over", 然后將原始圖像(要修補的圖像)繪制到hidden2上。
  3. 將hidden2的ctx.globalCompositeOperation設置為"destination-in", 然后將hidden1的內容繪制到hidden2上(即hidden2的ctx以hidden1為繪制源調用drawImage),這樣就將圖像上目標區域修補(摳)出來了。
  4. 以hidden2作為繪制源就可以將原始圖像上修補出的部分繪制到最終呈現的畫布上。此外,還可以加一層隱藏畫布hidden3,將hidden2的內容繪制到hidden3上,hidden3尺寸保持與原始圖像大小一致(若原始圖片尺寸過大也應該進行一定縮放,否則會影響性能),由此保證圖像放大后的清晰度,而最終呈現的畫布則以hidden3為繪制源進行繪制。

2. 其它說明

正如開頭所述,由於是不太常用的前端需求,加上完整的demo中在實現上涉及諸多細節,所以暫時未對demo源碼中任何部分進行展開。有感興趣或者有相關需求的朋友可以看一下源碼(注釋還算詳細),覺得不錯的話還請給個星吧,如有疑問歡迎評論區留言或聯系我。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM