app_tree_planting/components/image/compress.vue

396 lines
8.8 KiB
Vue
Raw Permalink Normal View History

2023-01-11 19:31:59 +08:00
<template xlang="wxml" minapp="mpvue">
<view class="imageCompress">
<view class="photo" v-if="result.length > 0">
<view class="item" v-for="(item, index) in result" :key="index">
<image :src="item.url" @tap="previewPhoto(item.url)" mode="widthFix"></image>
<view class="remote-photo-tag" @tap="removePhoto(index)"><image src="/static/images/icon-remove.png"></image></view>
</view>
</view>
<view class="upload" v-if="result.length < limit">
<view class="info" @tap="upload()">
<image src="/static/images/icon-photo.png"></image>
<text>{{ tip }}</text>
<text v-if="remark" class="remark">{{ remark }}</text>
</view>
</view>
<canvas
class="canvas"
:canvas-id="canvasId"
:style="'width:' + destWidth + 'px;height:' + destHeight + 'px;top:' + -canvasIndex * 9000 + 'px;left:' + -canvasIndex * 9000 + 'px'"
></canvas>
</view>
</template>
<script>
export default {
name: 'imageCompress',
props: {
/*图片类型*/
type: {
type: String,
default: 'water'
},
/*上传限制*/
limit: {
type: Number,
default: 1
},
/*最大允许宽度*/
maxWidth: {
type: Number,
default: 750
},
/*默认图片url单张*/
src: {
type: String,
default: ''
},
/*默认图片url多张*/
list: {
type: Array,
default: () => {
return [];
}
},
/*上传提示*/
tip: {
type: String,
default: ''
},
/*上传备注*/
remark: {
type: String,
default: ''
},
/*是否上传至服务端*/
isUploadServer: {
type: Boolean,
default: true
},
/*服务端url*/
serverUrl: {
type: String,
default: ''
}
},
data() {
return {
result: [],
uploadPhoto: [],
photoIndex: 0,
uploadIndex: 1,
canvasIndex: 1,
canvasId: 'canvas',
destWidth: 750,
destHeight: 750
};
},
created() {
/*默认值初始化*/
this.initDefaultValue();
// #ifdef H5
this.canvasId = Date.now().toString(36);
// #endif
},
watch: {
src: function(newVal, oldVal) {
if (this.result.length == 0 && this.src) {
console.log('refresh');
this.src = newVal;
this.initDefaultValue();
}
},
list: function(newVal, oldVal) {
if (this.result.length == 0 && this.list.length > 0) {
this.list = newVal;
this.initDefaultValue();
}
},
tip: function(newVal, oldVal) {
this.tip = newVal;
}
},
methods: {
/*初始化默认值*/
initDefaultValue() {
if (this.result.length == 0) {
/*单张*/
if (this.src) {
let data = { url: this.src };
this.result.push(data);
}
/*多张*/
if (this.list.length > 0) {
this.list.forEach(item => {
let data = { url: item };
this.result.push(data);
});
}
}
},
/*上传图片*/
upload() {
let maxUploadCount = this.limit;
if (this.limit > 1) {
maxUploadCount = this.limit - this.result.length;
}
uni.chooseImage({
count: maxUploadCount,
sizeType: ['compressed'], // 指定只能为压缩图,首先进行一次默认压缩
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
success: res => {
this.uploadPhoto = res.tempFilePaths;
this.uploadIndex = 0;
if (this.limit > 1 && this.uploadPhoto.length > maxUploadCount) {
if (this.result.length > 0) {
this.$alert('只能再上传' + maxUploadCount + '张', 'warning');
} else {
this.$alert('最多只能上传' + maxUploadCount + '张', 'warning');
}
return;
}
if (this.limit == 1) {
this.result = [];
this.$loading('图片上传…');
} else {
this.initLoading();
}
this.compress(this.uploadPhoto[this.uploadIndex]);
}
});
},
/*压缩图片*/
compress(photo) {
uni.getImageInfo({
src: photo,
success: imageInfo => {
let canvasWidth = imageInfo.width;
let canvasHeight = imageInfo.height;
while (canvasWidth > this.maxWidth) {
canvasWidth = this.maxWidth;
canvasHeight = Math.trunc((imageInfo.height / imageInfo.width) * this.maxWidth);
}
this.destWidth = canvasWidth;
this.destHeight = canvasHeight;
/*绘制时间*/
let ctxTime = 10;
// #ifdef H5
ctxTime = this.canvasTime();
// #endif
/*绘制类型*/
let fileType = imageInfo.path.replace(/^.+\./, '');
if (fileType == 'png') {
fileType = 'png';
} else {
fileType = 'jpg';
}
/*绘制*/
let ctx = wx.createCanvasContext(this.canvasId, this);
setTimeout(() => {
ctx.drawImage(imageInfo.path, 0, 0, this.destWidth, this.destHeight);
ctx.draw(false, () => {
/*绘制时间*/
let drawTime = 10;
// #ifdef MP
drawTime = this.canvasTime();
// #endif
setTimeout(() => {
uni.canvasToTempFilePath(
{
x: 0,
y: 0,
width: this.destWidth,
height: this.destHeight,
destWidth: this.destWidth,
destHeight: this.destHeight,
fileType: fileType,
canvasId: this.canvasId,
success: res => {
this.submit(res.tempFilePath);
/*上传多张*/
if (this.uploadPhoto.length - 1 != this.uploadIndex) {
this.uploadIndex = this.uploadIndex + 1;
this.initLoading();
this.compress(this.uploadPhoto[this.uploadIndex]);
}
},
fail: err => {
console.log(err);
},
complete: res => {
this.canvasIndex += 1;
// #ifdef H5
this.canvasId = Date.now().toString('36');
// #endif
}
},
this
);
}, drawTime);
});
}, ctxTime);
}
});
},
/*绘制时间*/
canvasTime() {
let time = this.maxWidth / 2;
if (time >= 600) {
return 600;
} else if (time <= 100) {
return 100;
} else {
return time;
}
},
/*刷新加载提示*/
initLoading() {
if (this.uploadPhoto.length > 1) {
let loadingTxt = '图片上传(' + (this.uploadIndex + 1) + '/' + this.uploadPhoto.length + '';
this.$loading(loadingTxt);
}
},
/*上传提交*/
submit(photoUrl) {
/*不上传服务端*/
if (!this.isUploadServer) {
let data = { url: photoUrl };
this.result.push(data);
this.$emit('upload', data);
if (this.uploadPhoto.length - 1 == this.uploadIndex) {
uni.hideLoading();
}
return;
}
/*默认上传url*/
let serverUrl = this.serverUrl;
if (serverUrl == '') {
serverUrl = this.$api.user.upload;
}
/*上传至服务端*/
this.$app.uploadFile({
url: serverUrl,
filePath: photoUrl,
name: 'file',
formData: { type: this.type },
success: res => {
if (res.code == 0) {
let data = { url: res.data.url, detail: res.data };
this.result.push(data);
console.log(this.result);
this.$emit('upload', data);
} else {
this.$alert(res.msg, 'warning');
}
},
complete: res => {
if (this.uploadPhoto.length - 1 == this.uploadIndex) {
uni.hideLoading();
}
}
});
},
/*删除图片*/
removePhoto(index) {
this.photoIndex -= 1;
this.result.splice(index, 1);
this.$emit('remove', index);
},
/*预览图片*/
previewPhoto(photoUrl) {
uni.previewImage({
current: 0,
urls: [photoUrl]
});
}
}
};
</script>
<style lang="scss" scoped>
.imageCompress {
.photo {
display: flex;
flex-direction: column;
margin: 0 30rpx;
.item {
position: relative;
margin: 34rpx 0 0;
width: 100%;
line-height: 0;
&:first-child {
margin-top: 20rpx;
}
&:last-child {
margin-bottom: 20rpx;
}
image {
width: 100%;
}
.remote-photo-tag {
position: absolute;
top: -20rpx;
right: -20rpx;
z-index: 100;
image {
width: 40rpx;
height: 40rpx;
}
}
}
}
.upload {
display: flex;
justify-content: center;
.info {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 500rpx;
height: 340rpx;
border: 1rpx dashed #026836;
border-radius: 10rpx;
margin-top: 34rpx;
padding: 15rpx 0;
&:first-child {
margin-top: 20rpx;
}
&:last-child {
margin-bottom: 20rpx;
}
image {
width: 100rpx;
height: 100rpx;
}
text {
padding: 15rpx 50rpx 0;
line-height: normal;
text-align: center;
}
.remark {
color: #848c98;
font-size: 24rpx;
}
}
}
.canvas {
position: fixed;
z-index: -9999;
}
}
</style>