实现效果:
可自定义中间内容及灰色区域背景图、背景色
实现说明:
1、使用原生html+css实现上传区域(因为支付宝小程序不兼容我的项目nut-ui的上传组件),改成别的ui组件也是可以的,反正全程处理的fileList
2、 使用Taro原生方法chooseImage实现图片选择,
3、 依旧是使用Taro实现的图片压缩。
代码部分:
html + css部分:
<view :class="styles.card">
<view :class="styles.license" @click="handleUploadClick" v-if="fileList?.length == 0">
<img :class="styles.uploadIcon" src="../../assets/img/icon-upload.png" alt="">
<text><slot>上传图片</slot></text>
</view>
<view :class="styles.previewContent" v-else>
<img :class="styles.previewImg" :src="fileList[0]?.url" alt="">
<IconFont :class="styles.delIcon" name="mask-close" color="rgba(0, 0, 0, 0.45)" @click="handleDeleteClick"></IconFont>
</view>
</view>
.card {
background: linear-gradient(to bottom, #E4ECFD 0%, #FFFFFF 40px, #FFFFFF 100%),rgba(255,255,255,0.5);
border-radius: 18px;
width: 100%;
height: 414px;
margin-bottom: 40px;
display: flex;
align-items: center;
justify-content: center;
}
.license {
width: 474px;
height: 300px;
background-color: rgba(0, 0, 0, 0.05);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-weight: 500;
font-size: 24px;
color: var(--color-font-light__5);
line-height: 28px;
}
.uploadIcon {
width: 52px;
height: 52px;
margin-bottom: 6px;
}
.previewContent {
width: 474px;
height: 300px;
border: 1px dashed #CACBD0;
border-radius: 18px;
position: relative;
}
.delIcon {
position: absolute;
top: -20px;
right: -20px;
display: inline-block;
z-index: 99;
}
.previewImg {
width: 100%;
height: 100%;
border-radius: 18px;
}
js部分
// js部分
// 选择图片 & 图片识别
const handleUploadClick = () => {
Taro.chooseImage({
count: 1,
sourceType: ['album', 'camera'],
success: async (res) => {
const tempFilePaths = res?.tempFilePaths;
if (tempFilePaths.length > 0) {
fileList.value = [{
url: tempFilePaths[0],
path: tempFilePaths[0]
}]
try {
Taro.showLoading({
title: '图片处理中...',
mask: true,
})
// 获取原始图片大小
const originalFileInfo = await Taro.getFileInfo({
filePath: tempFilePaths[0]
}) as { size: number }
console.log('原始文件大小:', (originalFileInfo.size / (1024 * 1024)).toFixed(2), 'MB')
// 压缩图片 -》我设置的压缩到6M内
compressImage(tempFilePaths[0], '', 6 * 1024 * 1024, 100, 5, (base64) =>{
// 请求图片上传接口
request({
url: 'XXXX',
body: {
"image": base64,
},
success: function (body) {
title: '图片上传成功',
icon: 'none'
})
Taro.hideLoading()
},
}).finally(() => {
Taro.hideLoading()
})
})
} catch (err) {
Taro.showToast({
title: '图片处理失败,请手动输入',
icon: 'none'
})
}
}
}
})
}
// 删除icon-》清空图片列表
const handleDeleteClick = () => {
fileList.value = [];
}
压缩图片逻辑封装:
/**
*小程序图片压缩到指定大小
* @param oldFilePath 原图地址
* @param filePath 压缩后的图片地址
* @param limitSize 图片大小kb
* @param quality 图片质量
* @param step 图片质量每次降低多少
* @param callback 回调
*/
export const compressImage = (
oldFilePath: string,
filePath: string,
limitSize: number = 7 * 1024 * 1024,
quality: number = 100,
step: number = 5,
callback: (base64: string) => void,
) => {
Taro.showLoading({
title: '图片处理中...',
mask: true,
})
const path = filePath === '' ? oldFilePath : filePath;
Taro.getFileSystemManager().getFileInfo({
filePath: path,
success: async (res) => {
console.log(`图片压缩size:${res.size / 1024 / 1024}m`, `quality:${quality}`, limitSize/ 1024 / 1024);
if (res.size > limitSize) {
Taro.compressImage({
src: oldFilePath,
quality: quality - step,
success(result) {
compressImage(
oldFilePath,
result.tempFilePath,
limitSize,
quality - step,
step,
callback,
);
},
});
} else {
console.log(
`压缩成功!size:${res.size / 1024 / 1024}m`,
`quality:${quality}`,
`path:${filePath}`,
);
Taro.getFileSystemManager().readFile({
filePath: path,
encoding: 'base64',
success: (res) => {
callback(res.data as string);
},
fail: (err) => {
callback(err.errMsg);
}
});
}
},
fail(res) {
Taro.showToast({
title: '图片解析失败,请重试',
icon: 'none'
})
Taro.hideLoading();
callback(res.errMsg);
},
});
};
end~
希望记录的问题能够帮助到你!