canvas drawImage繪圖實現contain和cover的效果


我們常用到css的background-size屬性中的contain和cover屬性,來實現背景圖的適配,

本文將要介紹在用canvas繪制圖片的時候,如何實現contain或cover效果呢?

contain概念

縮放背景圖片以完全裝入背景區,可能背景區部分空白。contain 盡可能的縮放背景並保持

圖像的寬高比例(圖像不會被壓縮)。該背景圖會填充所在的容器。當背景圖和容器的大小

不同時,容器的空白區域(上/下或者左/右)會顯示由 background-color 設置的背景顏色。

說白了就是保持圖片寬高比並保證圖片的長邊能完整顯示,用到canvas的 drawImage(img, dx, dy, dw, dh)方法

參數dx, dy分別表示圖片左上角頂點的橫 縱坐標

參數dw, dh分別表示定義圖片的寬 高。

公式推導

需要分兩種情況,

①當圖片寬高比 <= 畫布寬高比時,如圖:

已知:  
 imgRatio = imgWidth / imgHeight  canvasRatio = canvasWidth / canvasHeight 由圖得出條件:  imgHeight = canvasHeight 推導:  imgWidth = imgRatio * imgHeight = imgRatio * canvasHeight
即:
 dw = imgRatio * canvasHeight
 dh = canvasHeight
 dx = (canvasWidth - imgWidth) / 2  dy = 0

 

②當圖片的寬高比 >= canvas畫布寬高比時, 如圖:

同理推導出:
 imgWidth = canvasWidth
 imgHeight = imgWidth / imgRatio = canvasWidth / imgRatio

即: 
dw = canvasWidth
 dh = dw / imgRatio
 dx = 0
 dy = (canvasHeight - dh) / 2

所以以contain方式適應畫布的代碼為:

var canvas = document.getElementById('canvas'); var ctx = canvas.getContext('2d'); var img = new Image(); img.src = "images/pic1.jpg"; let dx, dy, dw, dh, imgRatio, canvasRatio; canvasRatio = canvas.width / canvas.height; // contain 方式
img.onload = function () {   imgRatio = img.width / img.height;   if(imgRatio <= canvasRatio){     dw = imgRatio * canvas.width     dh = canvas.height     dx = (canvas.width - dw) / 2     dy = 0   }else{     dw = canvas.width     dh = dw / imgRatio     dx = 0     dy = (canvas.height - dh) / 2   }   ctx.drawImage(img, dx, dy, dw, dh) }

 

cover概念

縮放背景圖片以完全覆蓋背景區,可能背景圖片部分看不見。和 contain 值相反,

cover 值盡可能大的縮放背景圖像並保持圖像的寬高比例(圖像不會被壓扁)。

該背景圖以它的全部寬或者高覆蓋所在容器。當容器和背景圖大小不同時,

背景圖的 左/右 或者 上/下 部分會被裁剪。

 說白了就是保持圖片寬高比的同時保證圖片的短邊能完全顯示出來,

因為可能會有裁剪,所以用到canvas的drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh)方法。

參數sx, sy分別表示源圖片被截取部分左上角頂點的橫 縱坐標

參數sw, sh 分別表示源圖片被截取部分的寬 高

參數 dx, dy, dw, dh 分別表示切片后將要在畫布上繪制的左上角頂點坐標及繪制的寬高。

公式推導

同樣分兩種情況,

① 圖片寬高比 <= 畫布寬高比時, 如圖:

已知: 
 imgRatio = imgWidth / imgHeight
 canvasRatio = canvasWidth / canvasHeight
由圖知:
 dw = canvasWidth
 dh = canvasHeight
 dx = 0
 dy = 0
此時圖片的寬要在畫布完整展示,所以源圖片要裁剪的區域為:

 sw = imgWidth
 sh = sw / canvasRatio
 sx = 0
 sy = (imgHeight - sh) / 2

 

②當圖片寬高比 >= 畫布寬高比時, 如圖:

 

同理:
 此時圖片的高要在畫布完整展示,源圖片的裁剪區域為:
 sh = imgHeight
 sw = sh * canvasRatio

 sx = (imgWidth - sw) / 2
 sy = 0

所以以cover方式適應畫布的代碼為:

var canvas = document.getElementById('canvas'); var ctx = canvas.getContext('2d'); var img = new Image(); img.src = "images/pic1.jpg"; let sx, sy, sw, sh, imgRatio, canvasRatio; canvasRatio = canvas.width / canvas.height; // cover 方式
img.onload = function () {   imgRatio = img.width / img.height;   if(imgRatio <= canvasRatio){     sw = img.width     sh = sw / canvasRatio     sx = 0     sy = (img.height - sh) / 2
  }else{
    sh = img.height
    sw = sh * canvasRatio
    sx = (img.width - sw) / 2
    sy = 0
  }   
  ctx.drawImage(img, sx, sy, sw, sh, 0, 0, canvas.width, canvas.height) // 因為是cover覆蓋, 所以dx,dy都是0,繪制寬高即為canvas寬高 
}

 


免責聲明!

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



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