vue关于移动端多图片上传预览以及压缩的那些事

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)
 })
 // 这样的话后端使用正常的读取文件的方法也是可以的

只能写成这样了,有问题的话欢迎指正和留言.

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值