一. 技术方案概述
在Vue3+Vite项目中实现图片前端压缩,主要涉及以下技术方案:
- 使用HTML5 Canvas API进行图片压缩
- 结合FileReader实现本地图片读取
- 通过Blob对象处理压缩后的图片数据
- 支持自定义压缩质量参数
- 兼容主流浏览器环境
二. 核心实现代码
2.1 图片压缩工具函数
/** * 图片压缩函数 *
* @param {File} file - 原始图片文件
* * @param {number} [quality=0.7] - 压缩质量(0-1之间)
* * @returns {Promise<Blob>} - 压缩后的图片Blob对象 */
const compressImage = async (file, quality = 0.7) => {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = async (e) => {
try {
const img = new Image()
img.onload = () => {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d') // 保持原始图片比例
const originalWidth = img.width
const originalHeight = img.height
let newWidth = originalWidth
let newHeight = originalHeight
if (newWidth > 2000) {
// 最大宽度限制
newWidth = 2000
newHeight = (newWidth / originalWidth) * originalHeight
}
canvas.width = newWidth
canvas.height = newHeight
// 绘制压缩后的图片
ctx.drawImage(img, 0, 0, newWidth, newHeight)
// 获取压缩后的数据
const blob = canvas.toBlob((blob) => { resolve(blob) }, 'image/jpeg', quality)
}
img.onerror = reject
} catch (error) { reject(error) }
}
reader.readAsDataURL(file)
})
}
2.2 Vue组件集成方案
<template>
<div>
<input type="file" accept="image/*" @change="handleFileUpload">
<button @click="uploadCompressed">上传压缩图片</button>
<div v-if="previewImage">
<img :src="previewImage" alt="预览" style="max-width: 100%">
</div>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const previewImage = ref(null)
const file = ref(null)
const handleFileUpload = (e) => {
file.value = e.target.files[0]
if (file.value) {
const reader = new FileReader()
reader.onload = () => { previewImage.value = reader.result }
reader.readAsDataURL(file.value)
}
}
const uploadCompressed = async () => {
if (!file.value) return
try { const compressedBlob = await compressImage(file.value, 0.7)
// 这里可以调用上传接口
// const formData = new FormData()
// formData.append('image', compressedBlob)
// await axios.post('/api/upload', formData)
console.log('压缩完成:', compressedBlob)
} catch (error) { console.error('压缩失败:', error) }
}
return { previewImage, handleFileUpload, uploadCompressed }
}
}
</script>
三. 技术实现细节
1、 压缩算法原理
- Canvas API压缩:通过canvas的toBlob方法,将图片绘制到canvas上并转换为Blob对象
- 质量参数控制:quality参数控制JPEG压缩质量(0-1),数值越小压缩率越高
- 尺寸自适应:根据原始尺寸自动调整,保持宽高比例
四. 完整项目集成方案
4.1 Vite配置优化
在vite.config.js中添加图片类型支持:
export default {
// ...
build: {
rollupOptions: {
output: {
assetFileNames: 'assets/[name].[ext]'
} } }}
4.2 错误处理方案
const compressImage = async (file, quality = 0.7) => {
return new Promise((resolve, reject) => {
// ...原有代码...
img.onerror = () => { reject(new Error('图片加载失败')) }
try {
// ...原有代码...
} catch (error) {
reject(error) } }) }
五. 兼容性处理
- 添加Polyfill支持旧浏览器
- 自动检测浏览器兼容性
- 提供降级方案(直接上传原图)