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在不同平台可能有细微差异

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

相关推荐
rzl025 分钟前
java web5(黑马)
java·开发语言·前端
Amy.Wang6 分钟前
前端如何实现电子签名
前端·javascript·html5
海天胜景8 分钟前
vue3 el-table 行筛选 设置为单选
javascript·vue.js·elementui
今天又在摸鱼9 分钟前
Vue3-组件化-Vue核心思想之一
前端·javascript·vue.js
蓝婷儿11 分钟前
每天一个前端小知识 Day 21 - 浏览器兼容性与 Polyfill 策略
前端
百锦再13 分钟前
Vue中对象赋值问题:对象引用被保留,仅部分属性被覆盖
前端·javascript·vue.js·vue·web·reactive·ref
jingling55517 分钟前
面试版-前端开发核心知识
开发语言·前端·javascript·vue.js·面试·前端框架
拾光拾趣录22 分钟前
CSS 深入解析:提升网页样式技巧与常见问题解决方案
前端·css
莫空000023 分钟前
深入理解JavaScript属性描述符:从数据属性到存取器属性
前端·面试
guojl24 分钟前
深度剖析Kafka读写机制
前端