Vue3 + Uniapp 图片压缩公共方法封装
下面是一个基于 Vue3 和 Uniapp 的图片压缩公共方法封装,支持多种图片格式,并考虑了兼容性问题。
实现代码
javascript
// utils/imageCompress.js
import { ref } from 'vue'
/**
* 图片压缩公共方法
* @param {Object} options 配置项
* @param {File|String} options.file 图片文件对象或临时路径
* @param {Number} [options.quality=0.8] 压缩质量 (0-1)
* @param {Number} [options.maxWidth=1920] 最大宽度
* @param {Number} [options.maxHeight=1080] 最大高度
* @param {String} [options.outputType='jpg'] 输出类型 (jpg/png)
* @returns {Promise<Object>} 返回压缩后的图片信息 {tempFilePath, size, width, height}
*/
export function useImageCompress() {
const compressing = ref(false)
const compressImage = async (options) => {
try {
compressing.value = true
// 参数处理
const {
file,
quality = 0.8,
maxWidth = 1920,
maxHeight = 1080,
outputType = 'jpg'
} = options
// 获取图片信息
let imgInfo = await getImageInfo(file)
// 计算压缩尺寸
const { width, height } = calculateSize(imgInfo.width, imgInfo.height, maxWidth, maxHeight)
// 执行压缩
const compressedResult = await uni.compressImage({
src: imgInfo.path,
quality: Math.floor(quality * 100),
width,
height,
compressLevel: 4, // 压缩等级 1-4
format: outputType === 'png' ? 'png' : 'jpg'
})
// 获取压缩后文件信息
const compressedInfo = await getImageInfo(compressedResult.tempFilePath)
return {
tempFilePath: compressedResult.tempFilePath,
size: compressedInfo.size,
width: compressedInfo.width,
height: compressedInfo.height
}
} catch (error) {
console.error('图片压缩失败:', error)
throw error
} finally {
compressing.value = false
}
}
// 获取图片信息
const getImageInfo = (file) => {
return new Promise((resolve, reject) => {
if (file instanceof File) {
// 处理File对象
const reader = new FileReader()
reader.onload = (e) => {
uni.getImageInfo({
src: e.target.result,
success: resolve,
fail: reject
})
}
reader.onerror = reject
reader.readAsDataURL(file)
} else {
// 处理临时路径
uni.getImageInfo({
src: file,
success: resolve,
fail: reject
})
}
})
}
// 计算压缩尺寸
const calculateSize = (originalWidth, originalHeight, maxWidth, maxHeight) => {
let width = originalWidth
let height = originalHeight
// 如果宽度超过最大值
if (width > maxWidth) {
const ratio = maxWidth / width
width = maxWidth
height = height * ratio
}
// 如果高度超过最大值
if (height > maxHeight) {
const ratio = maxHeight / height
height = maxHeight
width = width * ratio
}
return {
width: Math.round(width),
height: Math.round(height)
}
}
return {
compressing,
compressImage
}
}
使用方法
javascript
// 在组件中使用
import { useImageCompress } from '@/utils/imageCompress'
export default {
setup() {
const { compressing, compressImage } = useImageCompress()
const handleCompress = async (file) => {
try {
const result = await compressImage({
file,
quality: 0.7,
maxWidth: 800,
maxHeight: 800
})
console.log('压缩成功:', result)
// 使用压缩后的图片 result.tempFilePath
} catch (error) {
console.error('压缩失败:', error)
}
}
return {
compressing,
handleCompress
}
}
}
兼容性说明
-
多平台支持:
- 使用Uniapp的
uni.compressImage
API,兼容微信小程序、H5、App等多端 - 在小程序端使用微信原生压缩能力,性能较好
- 使用Uniapp的
-
图片类型支持:
- 支持JPG、PNG等常见格式
- 通过
outputType
参数可指定输出格式
-
大图处理:
- 自动计算缩放比例,防止内存溢出
- 分步处理:先获取信息,再压缩
-
性能优化:
- 添加
compressing
状态,防止重复压缩 - 合理的默认压缩参数
- 添加
-
错误处理:
- 完善的try-catch错误捕获
- 统一的返回格式
注意事项
- 微信小程序对压缩后的图片大小有限制(通常不超过2M)
- 在H5端,压缩效果依赖于浏览器实现
- 对于超大图片,建议先进行分块处理或提示用户选择较小的图片
- 压缩质量参数
quality
在不同平台可能有细微差异
这个封装提供了良好的灵活性和兼容性,可以根据实际需求调整参数或扩展功能。