2020-05-23 前端图片压缩
2020-05-23 本文已影响0人
FConfidence
前端完成图片压缩
流程
- 通过原生的input标签拿到要上传的图片文件
- 将图片文件转化成img元素标签
- 在canvas上压缩绘制该HTMLImageElement
- 将canvas绘制的图像转成blob文件
- 最后将该blob文件传到服务端
1. 使用Input标签来获取图片文件资源
<input type="file" accept="image/*" />
2. 读取文件转成img标签元素
// 先new一个img和fileReader的实例
const img = new Image()
const reader = new FileReader()// 读取文件资源
reader.readAsDataURL(file)
reader.onload = function(e) {
img.src = e.target.result
}
3. canvas压缩,核心步骤
const { width: originWidth, height: originHeight } = img;
// 最大尺寸限制
const maxWidth = 1000, maxHeihgt = 1000;
// 需要压缩的目标尺寸
let targetWidth = originWidth, targetHeight = originHeight
// 等比例计算超过最大限制时缩放后的图片尺寸
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实例,设置canvas的宽高度为压缩计算后的尺寸,并将img绘制到上面
// 创建画布
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
// 设置宽高度为等同于要压缩图片的尺寸
canvas.width = targetWidth
canvas.height = targetHeight
context.clearRect(0, 0, targetWidth, targetHeight)
//将img绘制到画布上
context.drawImage(img, 0, 0, targetWidth, targetHeight)
4. 转成blob文件
canvas.toBlob(callback, type, encoderOptions);
5. 将blob上传,大功告成
// 压缩前将file转换成img对象
function 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)
}
})
}
/**
* 压缩图片
* @param img 被压缩的img对象
* @param type 压缩后转换的文件类型
* @param mx 触发压缩的图片最大宽度限制
* @param mh 触发压缩的图片最大高度限制
*/
function 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
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)
canvas.toBlob(function(blob) {
resolve(blob)
}, type || 'image/png') })
}
// 文件上传
async function upload(file){
const img = await readImg(file)
const blob = await compressImg(img, file.type, 1000, 1000)
const formData = new FormData()
formData.append('file', blob, 'xxx.jpg')
axios.post('http://xxx.com/api',formData)
}
upload(file).catch(e => console.log(e))