Vue3 + Uniapp 图片压缩公共方法封装

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
    }
  }
}

兼容性说明

  1. 多平台支持

    • 使用Uniapp的uni.compressImageAPI,兼容微信小程序、H5、App等多端
    • 在小程序端使用微信原生压缩能力,性能较好
  2. 图片类型支持

    • 支持JPG、PNG等常见格式
    • 通过outputType参数可指定输出格式
  3. 大图处理

    • 自动计算缩放比例,防止内存溢出
    • 分步处理:先获取信息,再压缩
  4. 性能优化

    • 添加compressing状态,防止重复压缩
    • 合理的默认压缩参数
  5. 错误处理

    • 完善的try-catch错误捕获
    • 统一的返回格式

注意事项

  1. 微信小程序对压缩后的图片大小有限制(通常不超过2M)
  2. 在H5端,压缩效果依赖于浏览器实现
  3. 对于超大图片,建议先进行分块处理或提示用户选择较小的图片
  4. 压缩质量参数quality在不同平台可能有细微差异

这个封装提供了良好的灵活性和兼容性,可以根据实际需求调整参数或扩展功能。

相关推荐
lovepenny20 分钟前
Failed to resolve entry for package "js-demo-tools". The package may have ......
前端·npm
超凌27 分钟前
threejs 创建了10w条THREE.Line,销毁数据,等待了10秒
前端
车厘小团子1 小时前
🎨 前端多主题最佳实践:用 Less Map + generate-css 打造自动化主题系统
前端·架构·less
芒果1251 小时前
SVG图片通过img引入修改颜色
前端
海云前端11 小时前
前端面试ai对话聊天通信怎么实现?面试实际经验
前端
一枚前端小能手1 小时前
🔧 半夜被Bug叫醒的痛苦,错误监控帮你早发现
前端
Juchecar1 小时前
Vue 3 单页应用Router路由跳转示例
前端
这人是玩数学的1 小时前
在 Cursor 中规范化生成 UI 稿实践
前端·ai编程·cursor
UncleKyrie1 小时前
🎨 市面上主流 Figma to Code MCP 对比
前端
南半球与北海道#1 小时前
前端引入vue-super-flow流程图插件
前端·vue.js·流程图