最近遇到了个需要上传图片的需求,后端的接口对前端的图片大小有限制,但是具体限制多少咱也不知道,我看前辈代码是前端压缩图片然后再上传给后端,是基于canvas实现的,自己根据项目又稍微改动了一点点。话不多说上代码:
首先封装个canvas组件,我就直接贴代码了
<template>
<view>
<canvas class="canvas" canvas-id="canvas" :style="{
width: canvasStyle.width + 'px',
height: canvasStyle.height + 'px',
}"></canvas>
</view>
</template>
<script>
export default {
data() {
return {
//此处的是canvas 的尺寸 也可以通过props传递
canvasStyle: {
width: 500,
height: 500,
},
}
},
methods: {
compressImg(_this, src) {
let that = this
// 等比例压缩图片 可指定图片宽高
let w = that.canvasStyle.width;
let h = that.canvasStyle.height;
return new Promise((resolve, reject) => {
uni.getImageInfo({
src,
success(res) {
let originWidth = res.width;
let originHeight = res.height;
let maxWidth = w;
let maxHeight = h;
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开始绘制图片
let ctx = uni.createCanvasContext("canvas", _this)
ctx.clearRect(0, 0, targetWidth, targetHeight)
ctx.drawImage(src, 0, 0, maxWidth, maxHeight);
ctx.draw(
false,
setTimeout(() => {
uni.canvasToTempFilePath({
canvasId: "canvas",
destWidth: targetWidth,
destHeight: targetHeight,
fileType: "png",
quality: 0.4,
success: function(res1) {
resolve(res1);
},
fail: function(res) {
console.log(res.errMsg);
},
}, _this);
}, 1000)
);
},
fail(err) {
console.log(err.errMsg);
},
});
});
},
chooseImg() {
let that = this
uni.chooseImage({
count: 1,
sourceType: ['album', 'camera'],
sizeType: ['original', 'compressed'],
success: async (res) => {
uni.showLoading({
title: '正在上传...'
})
const result = await that.compressImg(this, res.tempFilePaths[0])
uni.showToast({
title: '上传成功',
icon: 'none'
})
//自定义事件,将绘制结果发出去
that.$emit('upload', result)
}
})
}
}
}
</script>
<style>
.canvas {
position: fixed;
left: -1000vm;
top: -1000vh;
}
</style>
在界面中去使用
import {addImgUrl } from '@/api/login.js'//引入api接口
import {
canvasPage
} from '@/components/canvas.vue' //uniapp引入组件====微信小程序引入方式在界面json中
//一定要注册,我老是忘记注册,或者直接在main.js中全局注册也许,省得每次都要引入注册
components: {
canvasPage,
},
//html结构中放
<canvas-page ref="canvasPage" @upload="upload"></canvas-page>
//methods方法
//事件触发上传
select_image() {
let that = this
//通过$ref调用组件中的方法去选取照片
that.$refs.canvasPage.chooseImg()
},
//组件的自定义事件,接收组件方法中绘制好的result
upload(val) {
let that = this
//addImgUrl是上传图片的接口名
addImgUrl({
path: val.tempFilePath,//文件路劲
fileName: '文件名'
}).then((res) => {
uni.hideLoading()
if (res.statusCode == 200) {
// 赋值给变量展示上传好的图片
that.imageUrl = (JSON.parse(res.data)).data.logoUrl
}
}).catch((err) => {
uni.hideLoading()
})
},