vue多图上传及压缩组件
<template>
<div class="upload">
<div class="preview-list">
<ul class="preview-list-wrapper" v-show="previewList.length">
<li v-for="(item, index) in previewList" :key="index">
<div class="preview-img">
<img :src="item">
<a href="javascript:;" class="close-icon" @click="delPreviewImg(index)"></a>
</div>
</li>
</ul>
<div class="default-preview" v-show="previewList.length < max">
<label class="default-preview-wrapper">
<img src="~static/img/default.svg">
<!-- capture="camera" -->
<input type="file" accept="image/*" class="file" :multiple="multiple" @change="change">
</label>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'upload',
data () {
return {
previewList: [],
uploadList: []
}
},
/*
* max 最大允许上传图片
* multiple 是否允许多选图片
* quality 压缩比例 默认0.6
*/
props: {
max: {
type: Number,
default: 5
},
multiple: {
type: Boolean,
default: false
},
quality: {
type: Number,
default: 0.6
}
},
methods: {
async change (e) {
const files = Array.prototype.slice.call(e.target.files)
const filesLen = files.length
if (this.previewList.length + filesLen <= 5 && filesLen) {
this.$loading.open()
this.preview(files)
} else {
this.$toast(`最多只能上传${this.max}张图片`)
}
},
async preview (files) {
files.forEach((file, i) => {
const size = file.size / 1024
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onloadend = () => {
if (size > 1024) {
this.canvasDataURL(reader.result, { quality: this.quality }, base64 => {
this.previewList.push(base64)
this.uploadList.push(this.convertBase64UrlToBlob(base64))
})
} else {
this.previewList.push(reader.result)
this.uploadList.push(this.convertBase64UrlToBlob(reader.result))
}
if (i === files.length - 1) {
this.$loading.close()
this.$emit('change', this.uploadList)
}
}
})
},
canvasDataURL (path, obj, callback) {
const img = new Image()
img.src = path
img.onload = (e) => {
// 默认按比例压缩
let w = img.width
let h = img.height
const scale = w / h
w = obj.width || w
h = obj.height || (w / scale)
let quality = 0.7 // 默认图片质量为0.7
// 生成canvas
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
// 创建属性节点
const anw = document.createAttribute('width')
anw.nodeValue = w
const anh = document.createAttribute('height')
anh.nodeValue = h
canvas.setAttributeNode(anw)
canvas.setAttributeNode(anh)
ctx.drawImage(img, 0, 0, w, h)
// 图像质量
if (obj.quality && obj.quality <= 1 && obj.quality > 0) {
quality = obj.quality
}
// quality值越小,所绘制出的图像越模糊
const base64 = canvas.toDataURL('image/jpeg', quality)
// 回调函数返回base64的值
callback(base64)
}
},
convertBase64UrlToBlob (urlData) {
const arr = urlData.split(',')
const mime = arr[0].match(/:(.*?);/)[1]
const bstr = atob(arr[1])
let n = bstr.length
const u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], { type: mime })
},
delPreviewImg (e) {
this.previewList.splice(e, 1)
}
}
}
</script>
<style lang="scss" scoped>
.upload {
.preview-list {
display: flex;
flex-wrap: wrap;
}
.preview-list-wrapper {
display: flex;
li {
margin-right: 0.4rem;
.preview-img {
position: relative;
width: 1rem;
height: 1rem;
border: 0.5px solid #9e9e9e;
box-sizing: border-box;
img {
width: 100%;
height: 100%;
}
.close-icon {
position: absolute;
top: -0.2rem;
right: -0.2rem;
width: 0.4rem;
height: 0.44rem;
background: url(~static/img/upload-close.png) center no-repeat;
background-size: 100%;
}
}
}
}
.default-preview {
.default-preview-wrapper {
width: 1rem;
height: 1rem;
display: flex;
align-items: center;
justify-content: center;
border: 0.5px solid #9e9e9e;
box-sizing: border-box;
img {
width: 0.41rem;
height: 0.41rem;
}
input.file {
width: 100%;
height: 100%;
display: none;
}
}
}
}
</style>
组件的调用
<upload :max="uploadSet.max" :multiple="uploadSet.multiple" @change="previewFinished"></upload>
这是最近项目需求写的一个多图片上传预览及压缩的一个vue组件,change事件返回上传的图片的blod二进制文件组成的数组,上传可以使用以下方法遍历,
cosnt formData = new FormData()
// this.uploadLis 为接收change事件返回的数据
this.uploadList.forEach((value, key) => {
formData.append('pic_list[]', value)
})
// 这样的话后端使用正常的读取文件的方法也是可以的
只能写成这样了,有问题的话欢迎指正和留言.