我們常用到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寬高
}