用vue3的写法结合uniapp在微信小程序中实现图片压缩、调整分辨率、做缩略图功能

在UniApp中使用Vue3实现微信小程序图片处理功能

下面是一个完整的UniApp组件实现,专门针对微信小程序环境,包含图片压缩、分辨率调整和缩略图生成功能。

完整组件代码

xml 复制代码
<template> 
<view class="image-processor">
<view class="header"> 
<text class="title">微信小程序图片处理工具</text>
</view>
<view class="upload-area" @click="chooseImage">
<text>点击选择图片</text> 
</view> 
<view v-if="originalImage" class="controls">
<view class="control-group">
<text>压缩质量 (0-100):</text> 
<slider :value="quality" min="0" max="100" @change="onQualityChange" show-value /> 
</view>
<view class="control-group">
<text>最大宽度:</text> 
<input type="number" v-model="maxWidth" min="100" />
</view> 
<view class="control-group">
<text>最大高度:</text> 
<input type="number" v-model="maxHeight" min="100" /> 
</view>
<view class="control-group">
<text>缩略图尺寸:</text> 
<input type="number" v-model="thumbnailSize" min="50" /> 
</view> 
<button @click="processImage" type="primary">处理图片</button> 
</view> 
<view v-if="processedImage" class="results">
<view class="image-container">
<text class="subtitle">原始图片 ({{ originalSize }})</text> 
<image :src="originalImage" mode="widthFix" class="original" />
</view>
<view class="image-container"> 
<text class="subtitle">处理后图片 ({{ processedSize }})</text>
<image :src="processedImage" mode="widthFix" class="processed" />
</view>
<view class="image-container" v-if="thumbnailImage">
<text class="subtitle">缩略图 ({{ thumbnailSize }}px)</text> 
<image :src="thumbnailImage" mode="widthFix" class="thumbnail" /> 
</view>
<button @click="saveImage" type="primary" class="download-btn">保存到相册</button> 
</view>
<canvas canvas-id="thumbnailCanvas" style="position: absolute; left: -9999px; width: 300px; height: 300px;"></canvas>
</view> 
</template>

js

ini 复制代码
import { ref } from 'vue';
const originalImage = ref(null); 
const processedImage = ref(null); 
const thumbnailImage = ref(null); 
const quality = ref(80);
const maxWidth = ref(800);
const maxHeight = ref(600); 
const thumbnailSize = ref(200);
const originalSize = ref('');
const processedSize = ref('');
const tempFilePath = ref('');
const chooseImage = async () => { 
try {
const res = await uni.chooseImage({
count: 1,
sourceType: ['album', 'camera'],
sizeType: ['original', 'compressed'] });
if (res.tempFilePaths.length > 0) { 
tempFilePath.value = res.tempFilePaths[0];
originalImage.value = tempFilePath.value; // 获取文件信息
const fileInfo = await uni.getFileInfo({
filePath: tempFilePath.value
});
originalSize.value = formatFileSize(fileInfo.size);
} } catch (error) { 
uni.showToast({ 
title: '选择图片失败', icon: 'none'
}); 
console.error(error);
} };
const onQualityChange = (e) => { 
quality.value = e.detail.value;
}; 
const processImage = async () => { 
if (!originalImage.value) return;
uni.showLoading({title: '处理中...' });
try { // 压缩并调整尺寸
const compressedRes = await uni.compressImage({
src: tempFilePath.value,
quality: quality.value, 
width: maxWidth.value, 
height: maxHeight.value
});
processedImage.value = compressedRes.tempFilePath; 
// 获取处理后文件大小 
const fileInfo = await uni.getFileInfo({ filePath: compressedRes.tempFilePath
});
processedSize.value = formatFileSize(fileInfo.size);
// 生成缩略图 
await generateThumbnail(compressedRes.tempFilePath);uni.hideLoading(); 
} catch (error) { 
uni.hideLoading();
uni.showToast({ 
title: '图片处理失败', icon: 'none'
}); console.error(error); } };
const generateThumbnail = async (filePath) => { 
try { 
// 使用canvas生成缩略图
const ctx = uni.createCanvasContext('thumbnailCanvas', this);
// 获取图片信息
const imgInfo = await new Promise((resolve, reject) => { 
uni.getImageInfo({
src: filePath, success: resolve, fail: reject });
}); 
// 计算缩略图尺寸,保持宽高比 
let width = thumbnailSize.value; 
let height = (imgInfo.height / imgInfo.width) * width; 
// 绘制缩略图
ctx.drawImage(filePath, 0, 0, width, height);
// 将canvas转为临时文件 
const tempFile = await new Promise((resolve, reject) => { 
ctx.draw(false, () => { 
uni.canvasToTempFilePath({ 
canvasId: 'thumbnailCanvas', quality: 0.7, success: resolve, fail: reject
}, this); }); }); 
thumbnailImage.value = tempFile.tempFilePath; 
} catch (error) { 
console.error('生成缩略图失败:', error);
} };
const saveImage = async () => { 
if (!processedImage.value) return;
try { await uni.saveImageToPhotosAlbum({ filePath: processedImage.value
});
uni.showToast({ title: '保存成功', icon: 'success' }); }
catch (error) { uni.showToast({ title: '保存失败', icon: 'none' });
console.error(error); } };
const formatFileSize = (bytes) => { 
if (bytes === 0) return '0 Bytes';
const k = 1024; 
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; }; ;

css

xml 复制代码
<style lang="scss">
.image-processor {
padding: 20rpx;
font-family: -apple-system, BlinkMacSystemFont, 
'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 
'Open Sans', 'Helvetica Neue', sans-serif;
} 
.header { 
margin-bottom: 30rpx; 
text-align: center; 
} 
.title { 
font-size: 36rpx; 
font-weight: bold;
} 
.upload-area {
margin: 30rpx 0;
padding: 40rpx;
border: 2rpx dashed #ccc;
border-radius: 10rpx;
text-align: center;
color: #666;
} 
.controls {
margin: 30rpx 0;
padding: 20rpx;
background: #f5f5f5; 
border-radius: 10rpx;
} 
.control-group {
margin-bottom: 20rpx;
text{
display: block;
margin-bottom: 10rpx;
font-size: 28rpx;
}
input {
border: 1rpx solid #ddd; 
padding: 10rpx;
border-radius: 5rpx;
width: 100%;
} } 
.results {
margin-top: 30rpx;
} 
.image-container {
margin-bottom: 30rpx;
border: 1rpx solid #eee;
padding: 20rpx;
border-radius: 10rpx;
} 
.subtitle {
display: block; 
margin-bottom: 15rpx; 
font-size: 28rpx;
font-weight: bold; 
} 
.original {
border: 4rpx solid #1890ff;
}
.processed {
border: 4rpx solid #52c41a;
}
.thumbnail {
border: 4rpx solid #faad14;
}
.download-btn { 
margin-top: 30rpx;
}
</style>
  1. API差异处理

    • 使用uni.chooseImage代替浏览器文件选择
    • 使用uni.compressImage进行图片压缩
    • 使用uni.canvasToTempFilePath将canvas转为图片
  2. 性能优化

    • 使用微信小程序的原生压缩API,性能更好
    • 隐藏的canvas用于生成缩略图,不影响界面
  3. 权限处理

    • 需要在小程序配置中声明相册权限
    • 处理用户拒绝授权的情况
相关推荐
Hilaku19 小时前
我用 Gemini 3 Pro 手搓了一个并发邮件群发神器(附源码)
前端·javascript·github
IT_陈寒19 小时前
Java性能调优实战:5个被低估却提升30%效率的JVM参数
前端·人工智能·后端
快手技术19 小时前
AAAI 2026|全面发力!快手斩获 3 篇 Oral,12 篇论文入选!
前端·后端·算法
颜酱19 小时前
前端算法必备:滑动窗口从入门到很熟练(最长/最短/计数三大类型)
前端·后端·算法
全栈前端老曹20 小时前
【包管理】npm init 项目名后底层发生了什么的完整逻辑
前端·javascript·npm·node.js·json·包管理·底层原理
HHHHHY20 小时前
mathjs简单实现一个数学计算公式及校验组件
前端·javascript·vue.js
boooooooom20 小时前
Vue3 provide/inject 跨层级通信:最佳实践与避坑指南
前端·vue.js
一颗烂土豆20 小时前
Vue 3 + Three.js 打造轻量级 3D 图表库 —— chart3
前端·vue.js·数据可视化
青莲84320 小时前
Android 动画机制完整详解
android·前端·面试
iReachers20 小时前
HTML打包APK(安卓APP)中下载功能常见问题和详细介绍
前端·javascript·html·html打包apk·网页打包app·下载功能