js canvas 前端实现修改图片尺寸压缩图片大小
阅读 (841) 2020-04-08 10:34:06
HTML5 <canvas> 元素用于图形的绘制,通过JavaScript将图片文件内容绘制到画布上,并修改图片宽高尺寸,导出文件二进制流
函数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);
官方描述:
/**
* 压缩图片
* @param img 被压缩的img对象
* @param type 压缩后转换的文件类型
* @param mx 触发压缩的图片最大宽度限制
* @param mh 触发压缩的图片最大高度限制
*/
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
})
})
}
更新于:2020-04-08 10:36:24