开发项目的时候碰到一个需求,由于用户的上传图片过大,需在上传前先将图片压缩到指定尺寸大小,再进行上传
实现步骤关键代码:
export const compressImg = (file: File): Promise<File> => {
return new Promise((resolve) => {
if (file.size > 3 * 1024 * 1024) {
const reader = new FileReader(),
name = file.name
// 生成canvas画布
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
reader.readAsDataURL(file) //转base64
reader.onload = function(e) {
const image = new Image()
image.src = e.target && e.target.result ? e.target.result.toString() : ''
image.onload = function() {
// 图片原始尺寸
const originWidth = image.width
const originHeight = image.height
// 设置最大尺寸限制
const maxWidth = 3500
const maxHeight = 3500
// 设置目标尺寸
let targetWidth = originWidth
let targetHeight = originHeight
// 图片尺寸超过1000x1000限制
if (originWidth > maxWidth || originHeight > maxHeight) {
if (originWidth / originHeight > maxWidth / maxHeight) {
// 更宽 按照宽度限定尺寸
targetWidth = maxWidth
targetHeight = Math.round(maxWidth * (originHeight / originWidth))
} else {
// 更高 按照高度限定尺寸
targetHeight = maxHeight
targetWidth = Math.round(maxHeight * (originWidth / originHeight))
}
}
// canvas对图片进行缩放
canvas.width = targetWidth
canvas.height = targetHeight
// 清除画布
if (context) context.clearRect(0, 0, targetWidth, targetHeight)
// 将图片划到canvas上
if (context) context.drawImage(image, 0, 0, targetWidth, targetHeight)
// data = canvas.toDataURL('image/jpeg', 0.86) // 压缩比例0.86,结果接近减小了一半
const data = canvas.toDataURL('image/jpeg', 0.6) // 压缩比例0.6
let arr = data.split(','),
mime = (arr as any)[0].match(/:(.*?);/)[1], // 转成blob
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
const files = new File([u8arr], name, { type: mime }) // 转成file
resolve(files)
}
}
} else {
resolve(file)
}
})
}
这里将压缩方法进行了封装。
原理是将图片转为canvas,然后进行压缩