js图片压缩文件上传、图片多选、canvas

233 阅读2分钟

效果:




要点:

  • 图片上传事件: <input type="file" accept="image/*" multiple class="file" id="file" @change="changeImg" >

  • let reader = new FileReader(); // 实例化FileReader

  • reader.readAsDataURL(file); // 将文件信息转成DataUrl(base64),转成功后执行 reader.onload 方法
    
    // 读取成功以后执行的方法
    reader.onload = e => {
      let img = new Image();
      img.src = e.target.result;
      img.onload = () => {
        this.imagetoCanvas(img); //Image 对象转变为一个 Canvas 类型对象,i为遍历的下标
      };
    };
  • 将一个 Image 对象转变为一个 Canvas 类型对象

    var cvs = document.createElement("canvas");
    var ctx = cvs.getContext("2d");
    cvs.width = image.width;
    cvs.height = image.height;
    ctx.drawImage(image, 0, 0, cvs.width, cvs.height);
  • 将一个 Canvas 对象压缩转变为一个 Blob 类型对象

    canvas.toBlob(
        function(blob) {
        },
        "image/jpeg",
        quality
    );

示例:

<template>
  <div class="upload">
    <div class="main">
      <div
        class="img_d"
        id="img_d"
        v-for="(v,i) in blogArr"
        :key="i"
      >
        <div class="img-centent">
          <img
            :src='v.url'
            alt=""
            id="img"
          >
        </div>
        <div class="del_d" @click="del(v,i)">
          <div class="del"></div>
        </div>
      </div>
      <input
        type="file"
        accept="image/*"
        multiple
        class="file"
        id="file"
        @change="changeImg"
      >
    </div>
  </div>
</template>

<script>
export default {
  name: "upload",
  data() {
    return {
      uploadNum_Max: 4, //图片上传数量上限

      blogArr: [] //压缩对象
    };
  },
  methods: {
    // 选择文件
    changeImg(e) {
      if (this.blogArr.length + e.target.files.length > this.uploadNum_Max) {
        alert(`最多上传${this.uploadNum_Max}张图片`);
        return;
      }

      for (let i = 0; i < e.target.files.length; i++) {
        let file = e.target.files[i]; // 拿到选择的文件信息(未压缩)
        console.log(file);
        let reader = new FileReader(); // 实例化FileReader
        reader.readAsDataURL(file); // 将文件信息转成DataUrl(base64),转成功后执行 reader.onload 方法

        // 读取成功以后执行的方法
        reader.onload = e => {
          let img = new Image();
          img.src = e.target.result;
          img.onload = () => {
            this.imagetoCanvas(img); //Image 对象转变为一个 Canvas 类型对象,i为遍历的下标
          };
        };
      }
    },

    // imagetoCanvas(image) 会将一个 Image 对象转变为一个 Canvas 类型对象,其中 image 参数传入一个Image对象
    imagetoCanvas(image) {
      var cvs = document.createElement("canvas");
      var ctx = cvs.getContext("2d");
      cvs.width = image.width;
      cvs.height = image.height;
      ctx.drawImage(image, 0, 0, cvs.width, cvs.height);
      let quality = 0.5;
      this.canvasResizetoFile(cvs, quality,image.src);//Canvas 对象压缩转变为一个 Blob 类型对象
    },

    //canvasResizetoFile(cvs,quality,fn) 会将一个 Canvas 对象压缩转变为一个 Blob 类型对象;其中 cvs 参数传入一个 Canvas 对象; quality 参数传入一个0-1的 number 类型,表示图片压缩质量;
    canvasResizetoFile(canvas, quality,src) {
      let _this = this;
      canvas.toBlob(
        function(blob) {
          _this.blogArr.push({
            url:src,
            file:blob
          });
          console.log(_this.blogArr); //得到压缩后的Blob 类型对象
        },
        "image/jpeg",
        quality
      );
    },

    // 删除图片
    del(e,i){
      this.blogArr.splice(i,1)
      console.log(this.blogArr)
    }
  }
};
</script>

<style lang="less" scoped>
@import "../LessStyle.less"; //引入公共样式
.upload {
  flex: 1;
  #style-display;
  .main {
    display: flex;
    align-items: center;
    .img_d {
      width: 80px;
      height: 80px;
      margin-right: 20px;
      position: relative;
      .img-centent {
        width: 100%;
        height: 100%;
        overflow: hidden;
        display: flex;
        align-items: center;
        justify-content: center;
        img {
          width: 150px;
        }
      }
      .del_d {
        position: absolute;
        width: 20px;
        height: 20px;
        background: red;
        border-radius: 50%;
        top: -10px;
        right: -10px;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        .del {
          width: 10px;
          height: 3px;
          background: white;
        }
      }
    }
  }
}
</style>