Canvas基本圖片操做與處理

前言

Canvas是H5中新增的技術,主要運用在圖片的處理和動畫的繪製上,隨着Canvas的使用場景愈來愈多,瞭解Canvas對平時開發大有裨益,這篇文章將介紹Canvas基本圖片操做與處理html

圖片上傳與繪製

將圖片上傳並繪製到Canva中是最多見的Canvas的圖片處理,這個上傳與繪製的過程是怎麼實現的呢?下面舉個例子:canvas

<canvas id="myCanvas"></canvas>
<input type="file" id="file">
let upload = document.getElementById('file')
upload.onchange = (event) => {
  let file = event.target.files[0]
  let fileReader = new FileReader()
  fileReader.onload = (e) => {
    let img = new Image()
    img.src = e.target.result
    img.onload = () => {
      let canvas = document.getElementById('myCanvas')
      canvas.width = img.width
      canvas.height = img.height
      let context = canvas.getContext('2d')
      context.drawImage(img, 0, 0)
    }
  }
  fileReader.readAsDataURL(file)
}

這個上傳與繪製的過程能夠總結爲兩步:api

  • 經過FileReader對象將input上傳的file對象轉化爲base64格式的圖片
  • 建立Image對象,將對象繪製在canvas上

這裏爲何要將base64格式的地址複製給Image對象,而後再將Image對象繪製到Canvas上而不是直接繪製呢?
這是由於Canvas上繪製時並不支持url做爲圖片源,Canvas只支持下面幾種圖片源:跨域

  • Image()函數構造的或者任何<img>元素
  • <video>元素做爲圖片源,能夠抓取當前幀做爲圖像
  • 另外一個<canvas>元素做爲源
  • 高性能位圖做爲圖片源

Canvas在繪圖時還有一個須要注意的點就是:Canvas在繪製不一樣域名下的圖片會出現跨域的錯誤,如圖:
image
被污染的Canvas,其實就是由於圖片跨域的問題的,這時須要兩步走:服務器

  • 圖片服務器響應頭添加Access-Control-Allow-Origin爲*或者指定域名
  • 設置Image的crossOrigin屬性img.setAttribute("crossOrigin",'Anonymous')

簡單示例代碼:cors

let img = new Image()
img.setAttribute("crossOrigin",'Anonymous')
img.src = './images/avatar.jpeg'
img.onload = () => {
  let canvas = document.getElementById('myCanvas')
  canvas.width = img.width
  canvas.height = img.height
  let context = canvas.getContext('2d')
  context.drawImage(img, 0, 0)
  console.log(canvas.toDataURL('image/png', 1.0))
}

更多跨域相關內容能夠看這裏ide

圖片變換

圖片縮放

Canvas中圖片縮放的其實是經過畫布的縮放來達到的,所以默認的縮放中心是在畫布原點(0, 0),可是通常狀況下咱們作縮放時都但願圖片中心是縮放中心,這裏有兩種辦法能達到圖片中心做爲縮放中心的縮放效果,接下來分別來看這兩種辦法的示例:
第一種:wordpress

let canvas = document.getElementById('myCanvas')
canvas.width = img.width
canvas.height = img.height
let context = canvas.getContext('2d')
context.translate(img.width / 2, img.height / 2)
context.scale(0.5, 0.5)
context.translate(-img.width / 2, -img.height / 2)
context.drawImage(img, 0, 0, img.width, img.height)

第一種方法就是畫布平移,先將畫布原點移到圖像中心,而後再作畫布縮放,再將畫布平移還原,最後繪製圖片,此時繪製的圖片就是以圖片中心作的縮放函數

第二種:性能

let canvas = document.getElementById('myCanvas')
canvas.width = img.width
canvas.height = img.height
let context = canvas.getContext('2d')
let paintWidth = img.width / 2
let paintHight = img.height / 2
let originX = 0 // 原圖片X座標
let originY = 0 // 原圖片Y座標
let paintX = originX + (img.width - paintWidth) / 2 // 縮放後的圖片X座標
let paintY = originY + (img.height - paintHight) / 2 // 縮放後的圖片Y座標
context.drawImage(img, paintX, paintY, paintWidth, paintHight)

第二種就是最直接的計算當圖片以左上角做爲縮放中心,縮放後的圖片位置產生的位置偏移,將位置偏移加上在進行圖片繪製

圖片旋轉

Canvas的圖片旋轉和圖片縮放同樣,默認的旋轉中心也是畫布的原點(0, 0),此時也須要平移畫布來實現圖片的中心旋轉,舉個例子

let img = new Image()
img.setAttribute("crossOrigin",'Anonymous')
img.src = './images/avatar.jpeg'
img.onload = () => {
let canvas = document.getElementById('myCanvas')
  canvas.width = img.width
  canvas.height = img.height
  let context = canvas.getContext('2d')
  context.translate(img.width / 2, img.height / 2)
  context.rotate(30 * Math.PI / 180)
  context.translate(-img.width / 2, -img.height / 2)
  context.drawImage(img, 0, 0, img.width, img.height)
}

鏡像變換

鏡像變換能夠以圖片垂直中線爲對稱軸,左右鏡像的變換叫水平鏡像,或者水平中線爲對稱軸,上下鏡像的變換叫垂直鏡像,通常水平鏡像用的比較多,這裏就來看一個水平鏡像的例子:

let img = new Image()
img.setAttribute("crossOrigin",'Anonymous')
img.src = './images/avatar.jpeg'
img.onload = () => {
  let canvas = document.getElementById('myCanvas')
  canvas.width = img.width
  canvas.height = img.height
  let context = canvas.getContext('2d')
  context.translate(img.width / 2, img.height / 2)
  context.scale(-1 , 1)
  context.translate(-img.width / 2, -img.height / 2)
  context.drawImage(img, 0, 0, img.width, img.height)
}

原圖:

水平鏡像:

鏡像操做的原理其實很簡單:就是將scale設置爲負值,當x軸的縮放爲負值時,就是水平鏡像,當y軸的縮放爲負值時就是垂直鏡像

對稱軸翻轉

對稱軸翻轉指的是圖片沿着左上角至右下角的對角線翻轉,來看用代碼Canvas是怎麼實現的:

let img = new Image()
img.setAttribute("crossOrigin",'Anonymous')
img.src = './images/avatar.jpeg'
img.onload = () => {
  let canvas = document.getElementById('myCanvas')
  canvas.width = img.width
  canvas.height = img.height
  let context = canvas.getContext('2d')
  context.translate(img.width / 2, img.height / 2)
  context.scale(-1 , 1)
  context.rotate(90 * Math.PI / 180)
  context.translate(-img.width / 2, -img.height / 2)
  context.drawImage(img, 0, 0, img.width, img.height)
}

翻轉圖:

實現原理:先作水平鏡像,而後順時針旋轉90度,因爲先作的水平鏡像,座標軸會被水平翻轉,順時針旋轉90度實際是逆時針旋轉90度

圖片灰度

圖片的灰度效果是Canvas很是常見的一個圖片處理效果,先來看實現灰度效果的代碼:

let img = new Image()
img.setAttribute("crossOrigin",'Anonymous')
img.src = './images/avatar.jpeg'
img.onload = () => {
  let canvas = document.getElementById('myCanvas')
  canvas.width = img.width
  canvas.height = img.height
  let context = canvas.getContext('2d')
  context.drawImage(img, 0, 0, img.width, img.height)
  let imageData = context.getImageData(0, 0, img.width, img.height)
  let data = imageData.data
  for (let i = 0; i < data.length; i += 4) {
    let average = (data[i] + data[i + 1] + data[i + 2]) / 3
    data[i] = average
    data[i + 1] = average
    data[i + 2] = average
  }
  context.putImageData(imageData, 0, 0)
}

灰度效果圖:


實現思路:

  • 先將圖片繪製在canvas上
  • 利用getImageData方法獲取每一個像素點的rgb值
  • 求出每一個像素點的rgb平均值,而後從新賦值
  • 利用putImageData將從新計算的imageData對象繪製到圖片上

這裏可能會有人對getImageData和putImageData這兩個api不是很熟悉,想要了解這個兩個api的能夠點getImageDataputImageData

總結

Canva在圖片的處理上凸顯的做用愈來愈大,所以寫了這篇文章對Canvas基本圖片操做與處理作了簡單的介紹,但願看了這篇文章對你們瞭解Canvas能有所幫助。若是有錯誤或不嚴謹的地方,歡迎批評指正,若是喜歡,歡迎點贊

相關文章
相關標籤/搜索