396 lines
8.8 KiB
Vue
396 lines
8.8 KiB
Vue
|
<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>
|