前端vue压缩静态图片,压缩gif动态图片
一、压缩静态图片
/**
* 压缩图片方法
* @param {file} file 文件
* @param {Number} quality 图片质量(取值 0-1 之间默认 0.52)
*/
export function compressImg(file, quality) {
let qualitys = 0.52
if (parseInt((file.size / 1024).toFixed(2)) < 1024) {
qualitys = 0.85
}
if (5 * 1024 < parseInt((file.size / 1024).toFixed(2))) {
qualitys = 0.92
}
if (quality) {
qualitys = quality
}
if (file[0]) {
return Promise.all(Array.from(file).map(e => this.compressImg(e, qualitys))) // 如果是 file 数组返回 Promise 数组
} else {
return new Promise((resolve) => {
if ((file.size / 1024).toFixed(2) < 300) {
resolve({
file: file
})
} else {
const reader = new FileReader() // 创建 FileReader
reader.readAsDataURL(file)
reader.onload = ({
target: {
result: src
}
}) => {
const image = new Image() // 创建 img 元素
image.onload = async () => {
const canvas = document.createElement('canvas') // 创建 canvas 元素
const context = canvas.getContext('2d')
const originWidth = image.width
const originHeight = image.height
let targetWidth = image.width
let targetHeight = image.height
if (1 * 1024 <= parseInt((file.size / 1024).toFixed(2)) && parseInt((file.size / 1024).toFixed(2)) <= 10 * 1024) {
var maxWidth = 1600
var maxHeight = 1600
targetWidth = originWidth
targetHeight = originHeight
// 图片尺寸超过的限制
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))
}
}
}
if (10 * 1024 <= parseInt((file.size / 1024).toFixed(2)) && parseInt((file.size / 1024).toFixed(2)) <= 20 * 1024) {
maxWidth = 1400
maxHeight = 1400
targetWidth = originWidth
targetHeight = originHeight
// 图片尺寸超过的限制
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.width = targetWidth
canvas.height = targetHeight
context.clearRect(0, 0, targetWidth, targetHeight)
context.drawImage(image, 0, 0, targetWidth, targetHeight) // 绘制 canvas
console.log('typetypetypetype',file.type);
const canvasURL = canvas.toDataURL(file.type, qualitys)
const buffer = atob(canvasURL.split(',')[1])
let length = buffer.length
const bufferArray = new Uint8Array(new ArrayBuffer(length))
while (length--) {
bufferArray[length] = buffer.charCodeAt(length)
}
const miniFile = new File([bufferArray], file.name, {
type: file.type
})
resolve({
origin: file,
file: miniFile,
beforeSrc: src,
afterSrc: canvasURL,
beforeKB: Number((file.size / 1024).toFixed(2)),
afterKB: Number((miniFile.size / 1024).toFixed(2)),
qualitys: qualitys
})
}
image.src = src
}
}
})
}
}
使用方式:
import { compressImg } from '@/utils/index'
// 第一个参数是file对象,第二个参数是压缩倍数,不传默认0.52
compressImg(file.raw)
二、gif动态图片压缩
参考网址:GitCode - 全球开发者的开源社区,开源代码托管平台
1.下载 npm i gifsicle-wasm-browser --save 包
npm i gifsicle-wasm-browser --save
2.在需要的页面或组件引入
import gifsicle from "gifsicle-wasm-browser";
3.使用方式
// 可以使用 async await 模式,也可以使用.then
gifsicle.run({
input: [{
file: file.raw,
name: 'input.gif',
}],
command: [`-O2 --lossy=160 input.gif -o /out/out.gif`],
}).then(outGifFiles => {
console.log(outGifFiles);
// [File,File,File ...]
});
博主压缩案例:可能是因为插件的原因,4mb以上进行压缩时间比较合适,小于4mb就不建议压缩了
//原图大小: 3320733 3.16MB
-O1 --lossy=20 1.gif -o /out/out.gif 压缩:19028574 20秒
-O1 --lossy=160 1.gif -o /out/out.gif 压缩:14047276 20秒
-O2 --lossy=40 1.gif -o /out/out.gif 压缩:3285702 34秒
-O2 --lossy=160 1.gif -o /out/out.gif 压缩:2957546 30秒
-O3 --lossy=160 1.gif -o /out/out.gif 压缩:2940185 83秒
//原图大小: 4883735 4.65MB
-O1 --lossy=20 1.gif -o /out/out.gif 压缩:4353783 6秒
-O1 --lossy=160 1.gif -o /out/out.gif 压缩:2324117 5秒
-O2 --lossy=40 1.gif -o /out/out.gif 压缩:3463351 9秒
-O2 --lossy=160 1.gif -o /out/out.gif 压缩:2479152 8秒
-O3 --lossy=160 1.gif -o /out/out.gif 压缩:2479108 20秒
//原图大小: 15482425 14.76MB
-O1 --lossy=20 1.gif -o /out/out.gif 压缩:15162166 11秒
-O1 --lossy=160 1.gif -o /out/out.gif 压缩:7987047 9秒
-O2 --lossy=40 1.gif -o /out/out.gif 压缩:10409003 20秒
-O2 --lossy=160 1.gif -o /out/out.gif 压缩:7233579 15秒
-O3 --lossy=160 1.gif -o /out/out.gif 压缩:7164005 45秒
const limit10M = file.size /1024/1024 < 10;
if(!limit10M) {
return this.$message.warning('上传文件不能超过10M!');
}
let newfile;
if( file.raw.type !=='image/gif'){
// 图片压缩
let res = await compressImg(file.raw)
newfile = res.file
}else{
// gif压缩 4MB以下不需要压缩
const limit4M = file.size /1024/1024 < 4;
if(!limit4M) {
let res = await gifsicle.run({
input: [{
file: file.raw,
name: 'input.gif',
}],
command: [`-O1 --lossy=20 input.gif -o /out/out.gif`],
})
console.log('resres',res);
newfile = res[0]
}else{
newfile = file.raw
}
}
// 使用 newfile 里面的值传入给后端
压缩案例对比图:查看下图