前言
前端利用cavans实现,参考了3种常用的图片压缩方法_huangpb0624的博客-CSDN博客
压缩效果主要看你设置的最大分辨率,使用笔者的设置压缩效果可以将10多m的图压缩到400k。
代码
wxml
<button bindtap="chooseImg">选择图片</button>
<canvas canvas-id="firstCanvas" style="width:{{ imgWidth }}px; height:{{ imgHeight }}px;"></canvas>
要隐藏canvas用这个
<canvas style="width:{{ imgWidth }}px; height:{{ imgHeight }}px;position: absolute; top: -9999px;" canvas-id="firstCanvas"></canvas>
ts/js
实现压缩后本地下载并上传云存储
// pages/upcompress/index.ts
Page({
/**
* 页面的初始数据
*/
data: {
imgWidth: 0,
imgHeight: 0
},
/**
* 生命周期函数--监听页面加载
*/
onLoad() {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
},
chooseImg () {
let _this = this;
// 从本地相册选择图片或使用相机拍照
wx.chooseImage({
count: 1, // 最多可以选择的图片张数
success (res) {
const ctx = wx.createCanvasContext('firstCanvas');
let path = res.tempFilePaths[0];
console.log("path",path)
wx.getImageInfo({
src: path,
success (res) {
console.log(res)
// 图片原始尺寸
let originWidth = res.width;
let originHeight = res.height;
// 最大尺寸限制,可通过设置宽高来实现图片压缩程度
let maxWidth = 1200,
maxHeight = 1600;
// 目标尺寸
let targetWidth = originWidth,
targetHeight = originHeight;
// 图片尺寸超过200x150的限制
if(originWidth > maxWidth || originHeight > maxHeight) {
if(originWidth / originHeight > maxWidth / maxHeight) {
// 更宽,按照宽度限定尺寸
targetWidth = maxWidth;
targetHeight = Math.round(maxWidth * (originHeight / originWidth));
} else {
targetHeight = maxHeight;
targetWidth = Math.round(maxHeight * (originWidth / originHeight));
}
}
// canvas对图片进行缩放
_this.setData({
imgWidth: targetWidth,
imgHeight: targetHeight
})
// 压缩图片(绘制图像到画布)
ctx.drawImage(path,0,0,targetWidth,targetHeight);
ctx.draw(false, ()=>{
// canvas导出为图片路径
wx.canvasToTempFilePath({
canvasId: 'firstCanvas',
fileType: 'jpg', //支持jpg或png
quality: 0.92, //图片质量
success(res) {
let compressedPath = res.tempFilePath;
// 使用原始文件名作为保存到系统相册的文件名
let fileName = path.split('/').pop();
// 上传压缩过的图片到云存储
wx.cloud.uploadFile({
cloudPath: 'compressed/' + fileName, // 云存储路径,包括文件名
filePath: compressedPath,
success: (uploadRes) => {
console.log('上传成功', uploadRes.fileID);
// 保存图片到系统相册
wx.saveImageToPhotosAlbum({
filePath: compressedPath,
success () {
console.log('保存到本地相册成功!')
},
fail () {
console.log('保存到本地相册失败!')
}
});
},
fail: (error) => {
console.error('上传失败', error);
}
});
},
fail(err) {
console.log(err);
}
});
});
}
});
}
});
},
})
微调
微调适配参考,在原有基础上修改,上传图片地址前,压缩完成后返回地址并上传
async uplunbo(){
const chooseResult = await wx.chooseImage({
//数量限制
count: 1,
sourceType: ['album'],
sizeType: ['compressed'],
});
this.uploadlunbo(chooseResult);
},
async uploadlunbo(chooseResult){
let that = this;
wx.showLoading({
title: '上传中',
});
const promises = chooseResult.tempFilePaths.map(async filePath => {
// 提取每个对象的tempFilePath
//const filePath = file.tempFilePath;//chooseMedia使用,不支持苹果
const fileName = filePath.split('/').pop();
const cloudPath = this.data.Path+ fileName;
const compressedFilePath = await this.compressImage(filePath);
console.log("filePath", filePath);// 这里压缩并返回路径
return wx.cloud.uploadFile({
cloudPath: cloudPath,
filePath: compressedFilePath,// 这里使用压缩后的路径
config: {
env: this.data.envId
}
});
});
Promise.all(promises).then(results => {
console.log('所有文件上传成功', results);
results.forEach((res, index) => {
this.setData({
haveGetImgSrc: true,
imgSrc: res.fileID
});
wx.cloud.callFunction({
name: 'uploadLunbo',
data: {
collectionName: lunboBase,
imgSrc: this.data.imgSrc,
folderValue: this.data.folderValue,
photoType: Number(this.data.op),
position: Number(this.data.position)
},
success: res => {
console.log("上传数据库成功", res);
that.refresherpulling()
// 执行其他操作
},
fail: error => {
console.log("上传数据库失败", error);
wx.showToast({
title: '上传数据库失败'
})
// 处理错误
}
});
});
}).catch(e => {
console.log(e);
wx.hideLoading();
wx.showToast({
title: '上传失败'
})
});
},
多图适配
多图压缩并上传,需要自适应cavans的数量和宽高。
wxml
<button bindtap="up">选择图片</button>
<block wx:for="{{ canvasList }}" wx:for-item="item" wx:for-index="index">
<canvas canvas-id="{{ 'canvas-' + index }}" style="width:{{ item.imgWidth }}px; height:{{ item.imgHeight }}px;position: absolute; top: -9999px;"></canvas>
</block>
js
Page({
data: {
imgWidth: 0,
imgHeight: 0,
canvasList: [], // 初始化一个数组,用于生成 canvas
},
async up(){
const chooseResult = await wx.chooseImage({
//数量限制
count: 1,
sourceType: ['album'],
sizeType: ['compressed'],
});
this.uploadColumn(chooseResult);
},
uploadColumn(chooseResult){
let that = this;
wx.showLoading({
title: '上传中',
});
this.setData({
countNo: 0,
canvasList: new Array(chooseResult.tempFilePaths.length).fill({ imgWidth: 0, imgHeight: 0 }) // 初始化每个项为对象
});
const promises = chooseResult.tempFilePaths.map(async (filePath, index) => {
const fileName = filePath.split('/').pop();
const cloudPath = this.data.Path + fileName;
const compressedFilePath = await this.compressImage(filePath, 'canvas-' + index);
return wx.cloud.uploadFile({
cloudPath: cloudPath,
filePath: compressedFilePath,
config: {
env: this.data.envId
}
});
});
Promise.all(promises).then(results => {
console.log('所有文件上传成功', results);
results.forEach((res, index) => {
this.setData({
haveGetImgSrc: true,
imgSrc: res.fileID
});
const no = Number(this.data.no) + index
console.log("no1", no);
wx.cloud.callFunction({
name: 'uploadColumn',
data: {
collectionName: this.data.columnBase,
imgSrc: this.data.imgSrc,
folderValue: this.data.folderValue,
position: Number(this.data.position),
text: this.data.describeValue,
no: Number(this.data.no) + index,
photoType: Number(this.data.photoTypeTmp),
},
success: function (res) {
console.log("上传数据库成功", res);
console.log("no2", no);
that.data.countNo++;
console.log("countNo",that.data.countNo);
// that.refresherpulling()
if(that.data.countNo==chooseResult.tempFiles.length){
console.log("全部上传数据库成功");
wx.hideLoading();
//归0,貌似有时候不能,还得开头归一次
that.setData({
countNo: 0,
});
setTimeout(() => {
//刷新
that.refresherpulling()
}, 100)
}
}
});
console.log("上传云存储成功", res);
});
this.setData({
no: Number(this.data.no) + chooseResult.tempFiles.length,
});
console.log("chooseResult.tempFiles.length", chooseResult.tempFiles.length);
}).catch(e => {
console.log(e);
wx.hideLoading();
wx.showToast({
title: '上传失败' + e
})
});
},
async compressImage(filePath, canvasId) {
let _this = this;
const index = Number(canvasId.split('-')[1]); // 获取canvasId中的索引
const canvasList = _this.data.canvasList;
return new Promise((resolve, reject) => {
const ctx = wx.createCanvasContext(canvasId);
wx.getImageInfo({
src: filePath,
success: res => {
const originWidth = res.width;
const originHeight = res.height;
const maxWidth = 600;
const maxHeight = 800;
let targetWidth = originWidth;
let targetHeight = originHeight;
if (originWidth > maxWidth || originHeight > maxHeight) {
if (originWidth / originHeight > maxWidth / maxHeight) {
targetWidth = maxWidth;
targetHeight = Math.round(maxWidth * (originHeight / originWidth));
} else {
targetHeight = maxHeight;
targetWidth = Math.round(maxHeight * (originWidth / originHeight));
}
}
// canvas对图片进行缩放
_this.setData({
['canvasList[' + index + '].imgWidth']: targetWidth,
['canvasList[' + index + '].imgHeight']: targetHeight
});
ctx.drawImage(filePath, 0, 0, targetWidth, targetHeight);
ctx.draw(false, () => {
wx.canvasToTempFilePath({
canvasId: canvasId,
fileType: 'jpg', //支持jpg或png
quality: 0.92, //图片质量
success: res => {
resolve(res.tempFilePath);
},
fail: err => {
reject(err);
}
});
});
},
fail: err => {
reject(err);
}
});
});
},
})