天天看點

js 壓縮html 圖檔上傳,js canvas 前端實作修改圖檔尺寸壓縮圖檔大小

函數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);

官方描述:

js 壓縮html 圖檔上傳,js canvas 前端實作修改圖檔尺寸壓縮圖檔大小

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

})

})

}