小程序使用相册
微信小程序提供了丰富的相册操作 API,允许开发者访问用户的相册、拍照、选择图片、保存图片等功能。这些功能主要通过 wx.chooseMedia、wx.saveImageToPhotosAlbum 等 API 实现。
下面是使用的一些示例:
1,定义变量
data: {
// 选择的图片列表
imageList: [],
// 当前选中的图片索引
currentIndex: 0,
// 是否显示预览
showPreview: false,
// 加载状态
loading: false,
// 保存结果提示
saveResult: ''
},
onLoad() {
console.log('相册页面加载');
this.checkAlbumPermission();
},
/**
* 检查相册权限
*/
checkAlbumPermission() {
wx.getSetting({
success: (res) => {
if (!res.authSetting['scope.writePhotosAlbum']) {
// 如果没有相册权限,提示用户授权
this.requestAlbumPermission();
}
}
});
},
/**
* 请求相册权限
*/
requestAlbumPermission() {
wx.authorize({
scope: 'scope.writePhotosAlbum',
success: () => {
console.log('相册权限授权成功');
},
fail: () => {
console.log('相册权限授权失败');
this.showPermissionGuide();
}
});
},
/**
* 显示权限引导
*/
showPermissionGuide() {
wx.showModal({
title: '权限提示',
content: '需要相册权限才能保存图片,请在设置中开启权限',
confirmText: '去设置',
success: (res) => {
if (res.confirm) {
wx.openSetting({
success: (res) => {
console.log('打开设置成功', res);
}
});
}
}
});
},
/**
* 选择相册图片
*/
chooseFromAlbum() {
wx.chooseMedia({
count: 9, // 最多选择9张
mediaType: ['image'], // 只选择图片
sourceType: ['album'], // 从相册选择
maxDuration: 30,
camera: 'back',
success: (res) => {
console.log('选择图片成功', res);
const tempFiles = res.tempFiles;
const newImageList = tempFiles.map((file, index) => ({
tempFilePath: file.tempFilePath,
size: file.size,
width: file.width,
height: file.height,
thumbTempFilePath: file.thumbTempFilePath,
id: Date.now() + index, // 生成唯一ID
selected: false
}));
// 合并到现有列表
this.setData({
imageList: [...this.data.imageList, ...newImageList],
saveResult: ''
});
wx.showToast({
title: `成功选择${newImageList.length}张图片`,
icon: 'success',
duration: 2000
});
},
fail: (err) => {
console.error('选择图片失败', err);
this.handleChooseError(err);
}
});
},
/**
* 拍照并选择
*/
takePhoto() {
wx.chooseMedia({
count: 1,
mediaType: ['image'],
sourceType: ['camera'], // 从相机拍照
camera: 'back',
success: (res) => {
console.log('拍照成功', res);
const file = res.tempFiles[0];
const newImage = {
tempFilePath: file.tempFilePath,
size: file.size,
width: file.width,
height: file.height,
thumbTempFilePath: file.thumbTempFilePath,
id: Date.now(),
selected: false,
isFromCamera: true // 标记来自相机
};
this.setData({
imageList: [newImage, ...this.data.imageList],
saveResult: ''
});
wx.showToast({
title: '拍照成功',
icon: 'success',
duration: 2000
});
},
fail: (err) => {
console.error('拍照失败', err);
this.handleChooseError(err);
}
});
},
/**
* 处理选择错误
*/
handleChooseError(err) {
let errorMsg = '选择图片失败';
switch (err.errMsg) {
case 'chooseMedia:fail auth deny':
errorMsg = '没有相册访问权限';
break;
case 'chooseMedia:fail cancel':
errorMsg = '用户取消了选择';
break;
case 'chooseMedia:fail no media':
errorMsg = '没有找到图片';
break;
default:
errorMsg = err.errMsg || errorMsg;
}
wx.showToast({
title: errorMsg,
icon: 'none',
duration: 2000
});
},
/**
* 预览图片
*/
previewImage(e) {
const index = e.currentTarget.dataset.index;
const urls = this.data.imageList.map(item => item.tempFilePath);
wx.previewImage({
current: urls[index],
urls: urls,
success: () => {
console.log('预览图片成功');
},
fail: (err) => {
console.error('预览图片失败', err);
wx.showToast({
title: '预览失败',
icon: 'none'
});
}
});
},
/**
* 选择/取消选择图片
*/
toggleSelect(e) {
const index = e.currentTarget.dataset.index;
const imageList = this.data.imageList.map((item, i) => {
if (i === index) {
return { ...item, selected: !item.selected };
}
return item;
});
this.setData({ imageList });
},
/**
* 全选/取消全选
*/
toggleSelectAll() {
const allSelected = this.data.imageList.every(item => item.selected);
const imageList = this.data.imageList.map(item => ({
...item,
selected: !allSelected
}));
this.setData({ imageList });
},
/**
* 获取选中的图片
*/
getSelectedImages() {
return this.data.imageList.filter(item => item.selected);
},
/**
* 保存选中图片到相册
*/
saveSelectedToAlbum() {
const selectedImages = this.getSelectedImages();
if (selectedImages.length === 0) {
wx.showToast({
title: '请先选择图片',
icon: 'none',
duration: 2000
});
return;
}
this.setData({ loading: true, saveResult: '' });
// 批量保存
this.batchSaveImages(selectedImages);
},
/**
* 批量保存图片
*/
async batchSaveImages(images) {
let successCount = 0;
let failCount = 0;
const results = [];
for (let i = 0; i < images.length; i++) {
try {
await this.saveSingleImage(images[i]);
successCount++;
results.push({ index: i, success: true });
} catch (error) {
failCount++;
results.push({ index: i, success: false, error: error.message });
}
// 更新进度
this.setData({
saveResult: `保存进度: ${i + 1}/${images.length}`
});
}
this.setData({ loading: false });
this.showSaveResult(successCount, failCount, results);
},
/**
* 保存单张图片
*/
saveSingleImage(image) {
return new Promise((resolve, reject) => {
wx.saveImageToPhotosAlbum({
filePath: image.tempFilePath,
success: () => {
console.log('保存图片成功', image.tempFilePath);
resolve();
},
fail: (err) => {
console.error('保存图片失败', err);
reject(new Error(this.getSaveErrorMsg(err)));
}
});
});
},
/**
* 获取保存错误信息
*/
getSaveErrorMsg(err) {
switch (err.errMsg) {
case 'saveImageToPhotosAlbum:fail auth deny':
return '没有相册写入权限';
case 'saveImageToPhotosAlbum:fail cancel':
return '用户取消了保存';
case 'saveImageToPhotosAlbum:fail no image':
return '图片文件不存在';
default:
return err.errMsg || '保存失败';
}
},
/**
* 显示保存结果
*/
showSaveResult(successCount, failCount, results) {
let title = '';
if (failCount === 0) {
title = `成功保存${successCount}张图片`;
} else if (successCount === 0) {
title = `保存失败,${failCount}张图片未保存`;
} else {
title = `成功${successCount}张,失败${failCount}张`;
}
this.setData({
saveResult: title
});
wx.showModal({
title: '保存结果',
content: title,
showCancel: false,
success: () => {
// 清空选择状态
const imageList = this.data.imageList.map(item => ({
...item,
selected: false
}));
this.setData({ imageList });
}
});
// 记录详细结果
console.log('保存详细结果:', results);
},
/**
* 压缩图片
*/
compressImage(imagePath) {
return new Promise((resolve, reject) => {
wx.compressImage({
src: imagePath,
quality: 80, // 压缩质量 0-100
success: (res) => {
console.log('图片压缩成功', res);
resolve(res.tempFilePath);
},
fail: (err) => {
console.error('图片压缩失败', err);
reject(err);
}
});
});
},
/**
* 获取图片信息
*/
getImageInfo(imagePath) {
return new Promise((resolve, reject) => {
wx.getImageInfo({
src: imagePath,
success: (res) => {
console.log('图片信息获取成功', res);
resolve(res);
},
fail: (err) => {
console.error('图片信息获取失败', err);
reject(err);
}
});
});
},
/**
* 批量压缩并保存
*/
async compressAndSaveSelected() {
const selectedImages = this.getSelectedImages();
if (selectedImages.length === 0) {
wx.showToast({
title: '请先选择图片',
icon: 'none'
});
return;
}
this.setData({ loading: true });
try {
// 先压缩所有图片
const compressedPaths = [];
for (const image of selectedImages) {
const compressedPath = await this.compressImage(image.tempFilePath);
compressedPaths.push(compressedPath);
}
// 保存压缩后的图片
for (let i = 0; i < compressedPaths.length; i++) {
await this.saveSingleImage({ tempFilePath: compressedPaths[i] });
this.setData({
saveResult: `压缩保存进度: ${i + 1}/${compressedPaths.length}`
});
}
this.setData({ loading: false });
this.showSaveResult(compressedPaths.length, 0, []);
} catch (error) {
this.setData({ loading: false });
wx.showToast({
title: '压缩保存失败',
icon: 'none'
});
}
},
/**
* 删除选中图片
*/
deleteSelected() {
const selectedImages = this.getSelectedImages();
if (selectedImages.length === 0) {
wx.showToast({
title: '请先选择要删除的图片',
icon: 'none'
});
return;
}
wx.showModal({
title: '确认删除',
content: `确定要删除选中的${selectedImages.length}张图片吗?`,
success: (res) => {
if (res.confirm) {
const remainingImages = this.data.imageList.filter(item => !item.selected);
this.setData({
imageList: remainingImages,
saveResult: `已删除${selectedImages.length}张图片`
});
wx.showToast({
title: '删除成功',
icon: 'success'
});
}
}
});
},
/**
* 清空所有图片
*/
clearAllImages() {
if (this.data.imageList.length === 0) {
wx.showToast({
title: '没有图片可清空',
icon: 'none'
});
return;
}
wx.showModal({
title: '确认清空',
content: '确定要清空所有图片吗?',
success: (res) => {
if (res.confirm) {
this.setData({
imageList: [],
saveResult: '已清空所有图片'
});
wx.showToast({
title: '清空成功',
icon: 'success'
});
}
}
});
},
/**
* 分享图片
*/
onShareAppMessage() {
const selectedImages = this.getSelectedImages();
if (selectedImages.length > 0) {
return {
title: `分享${selectedImages.length}张图片`,
path: '/pages/album/album',
imageUrl: selectedImages[0].thumbTempFilePath
};
}
return {
title: '分享我的相册',
path: '/pages/album/album'
};
},
/**
* 下拉刷新
*/
onPullDownRefresh() {
console.log('下拉刷新');
// 模拟刷新操作
setTimeout(() => {
this.setData({
saveResult: '刷新完成'
});
wx.stopPullDownRefresh();
wx.showToast({
title: '刷新成功',
icon: 'success'
});
}, 1000);
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onReachBottom() {
console.log('上拉加载更多');
// 可以在这里实现加载更多图片的逻辑
},
/**
* 用户点击右上角分享
*/
onShareTimeline() {
return {
title: '我的小程序相册',
imageUrl: '/images/share.jpg'
};
},
/**
* 错误处理统一函数
*/
handleError(error, operation = '操作') {
console.error(`${operation}失败:`, error);
wx.showToast({
title: `${operation}失败`,
icon: 'none',
duration: 2000
});
},
/**
* 性能优化:图片懒加载
*/
onImageLoad(e) {
const index = e.currentTarget.dataset.index;
console.log(`图片${index}加载完成`);
// 可以在这里添加图片加载完成的处理逻辑
},
/**
* 性能优化:图片加载失败
*/
onImageError(e) {
const index = e.currentTarget.dataset.index;
console.error(`图片${index}加载失败`);
// 可以在这里设置默认图片或重试逻辑
}
});
这是一个 WXML 文件:
<!-- pages/album/album.wxml -->
<view class="container">
<!-- 操作按钮区域 -->
<view class="action-buttons">
<button bindtap="chooseFromAlbum">选择相册</button>
<button bindtap="takePhoto">拍照</button>
<button bindtap="toggleSelectAll">全选/取消</button>
<button bindtap="saveSelectedToAlbum">保存选中</button>
<button bindtap="compressAndSaveSelected">压缩保存</button>
<button bindtap="deleteSelected">删除选中</button>
<button bindtap="clearAllImages">清空全部</button>
</view>
<!-- 状态显示 -->
<view class="status-info">
<text>已选择: {{imageList.length}} 张图片</text>
<text>选中: {{getSelectedImages().length}} 张</text>
<text>{{saveResult}}</text>
</view>
<!-- 图片列表 -->
<view class="image-grid">
<view
wx:for="{{imageList}}"
wx:key="id"
class="image-item {{item.selected ? 'selected' : ''}}"
bindtap="toggleSelect"
data-index="{{index}}"
>
<image
src="{{item.thumbTempFilePath}}"
mode="aspectFill"
bindload="onImageLoad"
binderror="onImageError"
data-index="{{index}}"
bindtap="previewImage"
/>
<view class="image-mask" wx:if="{{item.selected}}">✓</view>
</view>
</view>
<!-- 加载指示器 -->
<view wx:if="{{loading}}" class="loading">
<text>处理中...</text>
</view>
</view>
主要功能说明
- 图片选择功能
chooseFromAlbum(): 从相册选择图片
takePhoto(): 拍照获取图片
支持多选(最多 9 张)
错误处理和权限检查
- 图片管理功能
toggleSelect(): 选择/取消选择单张图片
toggleSelectAll(): 全选/取消全选
deleteSelected(): 删除选中图片
clearAllImages(): 清空所有图片
- 图片保存功能
saveSelectedToAlbum(): 保存选中图片到相册
compressAndSaveSelected(): 压缩后保存
批量保存,支持进度显示
详细的错误处理和结果反馈
- 图片处理功能
previewImage(): 预览大图
compressImage(): 图片压缩
getImageInfo(): 获取图片信息
- 权限管理
自动检查相册权限
引导用户授权
友好的错误提示
- 用户体验优化
加载状态显示
操作结果反馈
错误处理机制
性能优化(懒加载等)
这个示例提供了完整的相册操作功能,可以根据实际需求进行裁剪和扩展。
通关密语:相册