函數1:讀取圖檔資訊(主要是原使圖檔寬高)
readImg(file) {
return new Promise((resolve, reject) => {
const img = new Image()
const reader = new FileReader()
reader.onload = function(e) {
img.src = e.target.result
}
reader.onerror = function(e) {
reject(e)
}
reader.readAsDataURL(file)
img.onload = function() {
resolve(img)
}
img.onerror = function(e) {
reject(e)
}
})
}
函數2:修改圖檔尺寸(如原圖寬高尺寸2000*3000,現在手機拍照像素都很高,照片都在2-5兆,甚至更多大,此時我們将圖檔寬高尺寸修改到1000*1500,再儲存圖檔,那圖檔大小肯定就小了)
關于canvas.toBlob(callback, type, encoderOptions);
官方描述:
compressImg(img, type, mx, mh) {
return new Promise((resolve, reject) => {
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
const { width: originWidth, height: originHeight } = img
// 最大尺寸限制
const maxWidth = mx
const maxHeight = mh
// 目标尺寸
let targetWidth = originWidth
let targetHeight = originHeight
// 隻有寬高都超标時才按窄邊壓縮 (可以按自己需求修改判斷條件,如果在調用前就判斷了,那這裡就不用判斷 originWidth > maxWidth && originHeight > maxHeight,也可以改成 || 條件,看自己需求)
if (originWidth > maxWidth && originHeight > maxHeight) {
if (originWidth / originHeight > 1) {
// 寬圖檔
targetWidth = maxWidth
targetHeight = Math.round(maxWidth * (originHeight / originWidth))
} else {
// 高圖檔
targetHeight = maxHeight
targetWidth = Math.round(maxHeight * (originWidth / originHeight))
}
}
canvas.width = targetWidth
canvas.height = targetHeight
context.clearRect(0, 0, targetWidth, targetHeight)
// 圖檔繪制,新設定一個圖檔寬高,達到壓縮圖檔的目地
context.drawImage(img, 0, 0, targetWidth, targetHeight)
// 轉成blob, canvas toBlob函數有3個參數,第三個參數官方描述:Number類型,值在0與1之間,當請求圖檔格式為image/jpeg或者image/webp時用來指定圖檔展示品質。如果這個參數的值不在指定類型與範圍之内,則使用預設值,其餘參數将被忽略。
// 簡單點說就是修改圖檔展示品質,如果設定成0.1,那圖檔品質會壓縮的很差,一般在0.8以上可以保證圖檔在肉眼識别範圍不失真,如果對圖檔品質有要修,隻想修改圖檔寬高尺寸,那建議使用1,預設是0.92,會壓縮一點點
canvas.toBlob(function(blob) {
resolve(blob)
}, type || 'image/jpeg')
})
}
函數使用,例如我是在React中使用的,這裡需要用到 async 和 await 關鍵詞
async fileChange () {
console.log(this.fileInput)
// ref擷取檔案對象
var file = this.fileInput.files[0]
console.log(file.size) // 測試列印原檔案大小
const formData = new FormData()
const maxWidth = 1000 // 設定目标圖檔最大寬
const maxHeight = 1000 // 設定目标圖檔最大高
const img = await this.readImg(file)
const { width: originWidth, height: originHeight } = img
// 寬高都超标,則壓縮窄邊,否則直接用上傳的圖檔(這裡是我業務需求的條件判斷,可以按自己需求修改)
if (originWidth > maxWidth && originHeight > maxHeight) {
const blob = await this.compressImg(img, file.type, maxWidth, maxHeight)
formData.append('localImage', blob)
console.log('blob.size', blob.size) // 測試列印壓縮後的大小
} else {
formData.append('localImage', file)
}
// 這裡改成你自己上傳檔案的邏輯
Api.uploadFile('/app?api=uploadImage', formData, res => {
this.setState({
src: res.data
})
})
}