前端利用canvas給圖片添加水印

本文發佈於個人我的網站: http://wintc.top/article/27,轉載請註明。

  前兩天給我的網站添加了一個小功能,就是在文章編輯上傳圖片的時候自動給圖片加上水印。給網頁圖片添加水印是個常見的功能,也是互聯網內容做者保護本身版權的方法之一。本文簡單記錄一下藉助canvas在前端實現圖片添加水印的實現方法。
  canvas元素其實就是一個畫布,咱們能夠很方便地繪製一些文字、線條、圖形等,它也能夠將一個img標籤裏渲染的圖片畫在畫布上。
  在上傳文件到後端的時候,使用input標籤讀取用戶本地文件後獲得的實際上是一個Blob對象(更精確的說是File對象,特殊的Blob對象);而在頁面上展現一個圖片使用的是img標籤;繪製功能用canvas實現。添加水印的功能須要在img標籤、canvas畫布、Blob對象這三者之間相互轉換,經過一些API能夠完成這個工做:javascript

img、Blob、canvas相互轉化

  咱們能夠從本地讀取圖片Blob,而後渲染到img標籤,使用canvas繪製img內容而且繪製水印內容到畫布,再將canvas內容轉爲Blob對象上傳服務器,這樣就完整實現了圖片+水印的功能。前端

1、本地讀取圖像文件渲染到img標籤

  本地讀取圖片文件將會獲得一個Blob對象,咱們能夠藉助FileReader.readAsDataURL方法讀取Blob的內容,並獲得一個Base64編碼的文件內容,能夠將該內容賦值給img.src從而在瀏覽器上渲染出本地的圖像。固然,img並不是必須渲染到DOM樹。讀取操做是個異步操做,讀取完成會觸發load事件,爲了便於以後的調用,咱們能夠用一個Promise包裝這個操做,最後返回一個Promise對象。java

function blobToImg (blob) {
  return new Promise((resolve, reject) => {
    let reader = new FileReader()
    reader.addEventListener('load', () => {
      let img = new Image()
      img.src = reader.result
      img.addEventListener('load', () => resolve(img))
    })
    reader.readAsDataURL(blob)
  })
}

2、將img標籤內容繪製到canvas畫布

  調用canvas元素畫布上下文對象的drawImage方法便可實現將img內容繪製到畫布。canvas

function imgToCanvas (img) {
  let canvas = document.createElement('canvas')
  canvas.width = img.width
  canvas.height = img.height
  let ctx = canvas.getContext('2d')
  ctx.drawImage(img, 0, 0)
  return canvas
}

  drawImage這個方法能夠傳入多個參數,以定義繪製的圖像的範圍,這裏傳入的0, 0定義從圖像左上角開始繪製,後面能夠繼續傳入兩個參數來定義圖像的繪製終點,不過這裏整個圖片都要繪製到canvas,因此採用默認值便可。後端

3、canvas畫布上繪製水印並轉換爲Blob對象

  在圖片上傳的時候,咱們一般採用FormData,圖片文件以一個Blob對象的形式放到FormData中,因此咱們須要把canvas再轉爲Blob以便文件上傳等操做。利用HTMLCanvasElement.toBlob方法:瀏覽器

function watermark (canvas, text) {
  return new Promise((resolve, reject) => {
    let ctx = canvas.getContext('2d')
    // 設置填充字號和字體,樣式
    ctx.font = "24px 宋體"
    ctx.fillStyle = "#FFC82C"
    // 設置右對齊
    ctx.textAlign = 'right'
    // 在指定位置繪製文字,這裏指定距離右下角20座標的地方
    ctx.fillText(text, canvas.width - 20, canvas.height - 20)
    canvas.toBlob(blob => resolve(blob))
  })
}

4、圖片添加水印完整接口

  將以上三個步驟結合起來,就完整地實現了從圖片添加水印,下面是一個簡單的使用示例:從本地選擇一個圖片文件,而後添加水印後,在傳入的dom元素下預覽添加水印後的圖片。服務器

function imgWatermark (dom, text) {
  let input = document.createElement('input')
  input.setAttribute('type', 'file')
  input.setAttribute('accept', 'image/*')
  input.onchange = async () => {
    let img = await blobToImg(input.files[0])
    let canvas = imgToCanvas(img)
    let blob = await watermark(canvas, text)
    // 此處將Blob讀取到img標籤,並在dom內渲染出來;若是是上傳文件,能夠將blob添加到FormData中
    let newImage = await blobToImg(blob)
    dom.appendChild(newImage)
  }
  input.click()
}

  給頁面加一個id爲container的div元素,而後以下調用:app

let dom = document.querySelector('#container')
imgWatermark(dom, '水印文字')

  這樣就完整地給圖片添加了水印效果,下面看一下實際效果,你也能夠在線體驗dom

  添加水印前:異步

img、Blob、canvas相互轉化

  添加水印後(水印內容:「騰衝·清涼山」):

img、Blob、canvas相互轉化

5、總結

  本文僅僅介紹了圖像+水印文字的簡單實現,只是作了一些示例性的介紹,其實能夠實現更復雜的水印效果,好比圖像、半透明或漸變色文字等,可是原理都是同樣的。另外文中涉及的一些接口其實頗有用,好比一個常見功能是頭像上傳的預覽和剪裁,這時候你能夠利用FileReader來讀取文件內容預覽,利用CanvasRenderingContext2D.drawImage來實現剪裁功能。關於本文涉及接口的更多詳細用法,能夠參照MDN文檔,文章中的API都使用了連接的形式,你能夠快速查看它們的文檔。

相關文章
相關標籤/搜索