美文网首页
vue 移动端input上传图片之处理图片

vue 移动端input上传图片之处理图片

作者: YQSummer | 来源:发表于2020-11-16 11:21 被阅读0次

    前端开发中会有各种上传文件的需求,今天我们来说说上传图片
    上传图片

     <input  type="file" @change="imageChange($event)"  accept="image/*"  multiple />       
    

    type:"file" 上传文件的格式
    multiple :multiple 多张上传(不设置的话就是单张上传啦)
    accept:image/* 上传类型(这里设置的是image/*,就是上传图片的所有类型啦,我们可以更加项目需求设置不同的类型 image/gif, image/jpeg)
    点击input 选择图片触发@change="imageChange($event)"事件
    选择后我们的到的是二进制流,
    现在各大手机拍出的照片大小不一样,我们需要压缩图片,还要处理一部分手机照片上传后会有旋转的问题

    // 上传图片
         imageChange(e){
         //e  选择图片后返回的所有参数  是数组的形式
           var imgs = e.target.files || e.dataTransfer.files;
           if (!imgs.length) return;
           let self = this
             for(var i=0;i<imgs.length;i++) {
               this.blobToBase64(imgs[i])  //转成 base64       
           }
         },
    

    获取到的二进制文件 转 base64文件
    这里需要引入插件 import EXIF from "exif-js"; ios上传照片会有旋转的问题
    npm install exif-js -s

     /**
           * 获取到的二进制文件 转 base64文件
           * @param blob
           */
          blobToBase64 (blob) {
            const self = this // 绑定this
            const reader = new FileReader() //实例化一个reader文件
            reader.readAsDataURL(blob) // 添加二进制文件
            reader.onload = function (event) {
              const base64 = event.target.result // 获取到它的base64文件
              const scale = 0.3  // 设置缩放比例 (0-1)
              if(self.isiOS){  //判断是否是ios
    //ios上传图片时会根据拍照时是横屏还是竖屏拍摄,图片会旋转的,我们要将图片旋转成正常
                EXIF.getData(blob, function() {
                  EXIF.getAllTags(this);
                  var  orientation = EXIF.getTag(this, 'Orientation');
                  self.compressImg(base64,orientation, scale, self.gotoService) // 调用压缩方法
                 //self.gotoService  压缩后上传至服务器
                });
              }else{
                self.compressImg(base64,0, scale, self.gotoService) // 调用压缩方法
              }
            }
          },
    

    压缩图片方法

     /* 压缩图片方法
           * @param base64  ----baser64文件
             * @param scale ----压缩比例 画面质量0-9,数字越小文件越小画质越差
           * @param callback ---回调函数
           */
          compressImg (base64, orientation,scale, callback) {
            // 处理缩放,转换格式
     
            let self = this;
            const img = new Image() //new 一个图片
            img.src = base64
            img.onload = function () {
              const canvas = document.createElement('canvas') //    用canvas来压缩
              const ctx = canvas.getContext('2d')
              canvas.setAttribute('width', this.width)
              canvas.setAttribute('height', this.height)
              ctx.clearRect(0, 0, canvas.width, canvas.height)
              ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
              if(isIos){ //ios处理图片旋转
                if(orientation != "" && orientation != 1){
                  switch(orientation){
                    case 6://需要顺时针(向左)90度旋转
                      self.rotateImg(img,'left',canvas);
                      break;
                    case 8://需要逆时针(向右)90度旋转
                      self.rotateImg(img,'right',canvas);
                      break;
                    case 3://需要180度旋转
                      self.rotateImg(img,'right',canvas);//转两次
                      self.rotateImg(img,'right',canvas);
                      break;
                  }
                }
              }
              // 转成base64 文件
              let base64 = canvas.toDataURL('image/jpeg')
              // 根据自己需求填写大小 我的目标是小于2兆
              while (base64.length > 1024 * 1024 * 2) {
                scale -= 0.01
                base64 = canvas.toDataURL('image/jpeg', scale)
              }
              // baser64 TO blob 这一块如果不懂可以自行百度,我就不加注释了
              const arr = base64.split(',')
              const mime = arr[0].match(/:(.*?);/)[1]
              const bytes = atob(arr[1])
              const bytesLength = bytes.length
              const u8arr = new Uint8Array(bytesLength)
              for (let i = 0; i < bytes.length; i++) {
                u8arr[i] = bytes.charCodeAt(i)
              }
              const blob = new Blob([u8arr], { type: mime })
              // 回调函数 根据需求返回二进制数据或者base64数据,我的项目都给返回了
              callback(blob, base64)
            }
          },
    

    图片旋转

     //图片旋转
          rotateImg(img, direction, canvas) {
            //最小与最大旋转方向,图片旋转4次后回到原方向
            var min_step = 0;
            var max_step = 3;
            //var img = document.getElementById(pid);
            if (img == null)return;
            var height = canvas.height;
            var width = canvas.width;
            //var step = img.getAttribute('step');
            var step = 2;
            if (step == null) {
              step = min_step;
            }
            if (direction == 'right') {
              step++;
              //旋转到原位置,即超过最大值
              step > max_step && (step = min_step);
            } else {
              step--;
              step < min_step && (step = max_step);
            }
            //旋转角度以弧度值为参数
            var degree = step * 90 * Math.PI / 180;
            var ctx = canvas.getContext('2d');
            switch (step) {
              case 0:
                canvas.width = width;
                canvas.height = height;
                ctx.drawImage(img, 0, 0, width, height);
                break;
              case 1:
                canvas.width = height;
                canvas.height = width;
                ctx.rotate(degree);
                ctx.drawImage(img, 0, -height, width, height);
                break;
              case 2:
                canvas.width = width;
                canvas.height = height;
                ctx.rotate(degree);
                ctx.drawImage(img, -width, -height, width, height);
                break;
              case 3:
                canvas.width = height;
                canvas.height = width;
                ctx.rotate(degree);
                ctx.drawImage(img, -width, 0, width, height);
                break;
            }
          },
    

    上传图片服务器

        //上传图片服务器
          gotoService(blob, base64){
            if (blob.size >= 2*1024*1024) {
              Toast('图片不得大于2M')
              return
            } else {
              var param = new FormData()
              param.append('file', blob, '.jpg')
              param.append('filename', blob + '.jpg')
              param.append('type', '1')
              let that = this
          //下面是用axios上传图片至服务器  根据自定义的项目api上传至服务器即可
              onUpload(param).then(res => {
                if (res.code == 200) {          
                  that.images.push(res.data)
                } else {
                  Toast({message:'上传失败'), duration: 2000})
                }
              })
            }
          },
    

    到这里上传图片中的问题就都解决了,压缩图片,旋转图片 ,上传图片
    如有不足,欢迎各位指导

    相关文章

      网友评论

          本文标题:vue 移动端input上传图片之处理图片

          本文链接:https://www.haomeiwen.com/subject/zfhbvktx.html