zoukankan      html  css  js  c++  java
  • vue 上传图片视频组件,可拍照选择照片,解决苹果手机拍照旋转问题

    1.创建组件components > uploadImg > index.vue

    <template>
      <input type="file" name="pic" ref="file" accept="image/*" @change="upload"/>
    </template>
    
    <script>
    import Exif from "exif-js";
    import { upload } from "@/api";
    
    export default {
      props: {
      },
      data() {
        return {
          uploadName: ""
        };
      },
      mounted() {
        console.log(this.uploadType);
      },
      methods: {
        upload(e) {
          if (e.target.files.length > 0) {
            this.$vux.loading.show("Loading...");
            let files = e.target.files || e.dataTransfer.files;
            if (!files.length) return;
            this.picValue = files[0]
            this.uploadName = files[0].name;
    
            // 上传图片
            var u = navigator.userAgent, app = navigator.appVersion;
            var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1; //g
            var isIOS = !!u.match(/(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
            if (isAndroid) {
              this.axiosFun(this.picValue);
            }
            if (isIOS) {
           this.imgPreview(this.picValue);
            }
    
            // 上传视频
            // this.axiosFun(this.picValue);
          }
        },
        imgPreview(file) {
          let self = this;
          let Orientation;
          //去获取拍照时的信息,解决拍出来的照片旋转问题
          Exif.getData(file, function() {
            Orientation = Exif.getTag(this, "Orientation");
          });
          // 看支持不支持FileReader
          if (!file || !window.FileReader) return;
    
          if (/^image/.test(file.type)) {
            // 创建一个reader
            let reader = new FileReader();
    
            // 将图片2将转成 base64 格式
            reader.readAsDataURL(file);
    
            // 读取成功后的回调
            reader.onloadend = function() {
              let result = this.result;
              let img = new Image();
              img.src = result;
              //判断图片是否大于100K,是就直接上传,反之压缩图片
              if (this.result.length <= 100 * 1024) {
                self.headerImage = this.result;
                self.postImg();
              } else {
                img.onload = function() {
                  let data = self.compress(img, Orientation);
                  self.headerImage = data;
                  self.postImg();
                };
              }
            };
          }
        },
        compress(img, Orientation) {
          let _this = this
          let canvas = document.createElement("canvas");
          let ctx = canvas.getContext("2d");
          //瓦片canvas
          let tCanvas = document.createElement("canvas");
          let tctx = tCanvas.getContext("2d");
          let initSize = img.src.length;
          let width = img.width;
          let height = img.height;
          //如果图片大于四百万像素,计算压缩比并将大小压至400万以下
          let ratio;
          if ((ratio = width * height / 4000000) > 1) {
            console.log("大于400万像素");
            ratio = Math.sqrt(ratio);
            width /= ratio;
            height /= ratio;
          } else {
            ratio = 1;
          }
          canvas.width = width;
          canvas.height = height;
          //        铺底色
          ctx.fillStyle = "#fff";
          ctx.fillRect(0, 0, canvas.width, canvas.height);
          //如果图片像素大于100万则使用瓦片绘制
          let count;
          if ((count = width * height / 1000000) > 1) {
            console.log("超过100W像素");
            count = ~~(Math.sqrt(count) + 1); //计算要分成多少块瓦片
            //            计算每块瓦片的宽和高
            let nw = ~~(width / count);
            let nh = ~~(height / count);
            tCanvas.width = nw;
            tCanvas.height = nh;
            for (let i = 0; i < count; i++) {
              for (let j = 0; j < count; j++) {
                tctx.drawImage(
                  img,
                  i * nw * ratio,
                  j * nh * ratio,
                  nw * ratio,
                  nh * ratio,
                  0,
                  0,
                  nw,
                  nh
                );
                ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
              }
            }
          } else {
            ctx.drawImage(img, 0, 0, width, height);
          }
          //修复ios上传图片的时候 被旋转的问题
          if (Orientation != "" && Orientation != 1) {
            switch (Orientation) {
              case 6: //需要顺时针(向左)90度旋转
                _this.rotateImg(img, "left", canvas);
                break;
              case 8: //需要逆时针(向右)90度旋转
                _this.rotateImg(img, "right", canvas);
                break;
              case 3: //需要180度旋转
                _this.rotateImg(img, "right2", canvas);
                break;
            }
          }
          //进行最小压缩
          let ndata = canvas.toDataURL("image/jpeg", 0.1);
          tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
          return ndata;
        },
        rotateImg(img, direction, canvas) {
          //最小与最大旋转方向,图片旋转4次后回到原方向
          const min_step = 0;
          const max_step = 3;
          if (img == null) return;
          //img的高度和宽度不能在img元素隐藏后获取,否则会出错
          let height = img.height;
          let width = img.width;
          let step = 2;
          if (step == null) {
            step = min_step;
          }
          if (direction == "right") {
            step++;
            //旋转到原位置,即超过最大值
            step > max_step && (step = min_step);
          } else if (direction == "right2") {
            step = 2;
          } else {
            step--;
            step < min_step && (step = max_step)
          }
          //旋转角度以弧度值为参数
          let degree = step * 90 * Math.PI / 180;
          let ctx = canvas.getContext("2d");
          switch (step) {
            case 0:
              canvas.width = width;
              canvas.height = height;
              ctx.drawImage(img, 0, 0);
              break;
            case 1:
              canvas.width = height;
              canvas.height = width;
              ctx.rotate(degree);
              ctx.drawImage(img, 0, -height);
              break;
            case 2:
              canvas.width = width;
              canvas.height = height;
              ctx.rotate(degree);
              ctx.drawImage(img, -width, -height);
              break;
            case 3:
              canvas.width = height;
              canvas.height = width;
              ctx.rotate(degree);
              ctx.drawImage(img, -width, 0);
              break;
          }
        },
        postImg() {
          //这里写接口
          // console.log(this.headerImage)
          const block = this.headerImage.split(";");
    
          const contentType = block[0].split(":")[1]; // In this case "image/jpeg"
    
          const realData = block[1].split(",")[1]; // In this case "R0lGODlhPQBEAPeoAJosM...."
    
          var blob = this.b64toBlob(realData, contentType);
          this.axiosFun(blob);
        },
        uploadDefined(file, data, callback) {
          let _this = this;
          let gObjectName = data.dir + this.randomString() + this.getSuffix(this.uploadName);
          let request = new FormData();
          request.append("OSSAccessKeyId", data.accessid); // Bucket 拥有者的Access Key Id。
          request.append("policy", data.policy); // policy规定了请求的表单域的合法性
          request.append("Signature", data.signature); // 根据Access Key Secret和policy计算的签名信息,OSS验证该签名信息从而验证该Post请求的合法性
          request.append("key", gObjectName); // 文件名字,可设置路径
          request.append("success_action_status", "200"); // 让服务端返回200,不然,默认会返回204
          request.append("x-oss-object-acl", "public-read");
          request.append("file", file);
    
          let xhr = new XMLHttpRequest();
          xhr.open("POST", data.host);
          xhr.send(request);
          xhr.onreadystatechange = function() {
            if (xhr.readyState === 4 && xhr.status === 200) {
              // console.log("fileKey => " + data.host + "/" + gObjectName);
              // console.log(_this.imgPaths);
              _this.$vux.loading.hide();                
              callback(data.host, gObjectName);
            } else if (xhr.status === 400){
              _this.$vux.loading.hide();
              _this.$vux.toast.text('图片太大,请换取小的图片')
            }
          };
        },
        async imgUpload(){
          // const { data } = await uploadImg({url: host, })
        },
        async axiosFun(blob) {
          let that = this;
          const { data } = await upload({});
    
          that.uploadDefined(blob, data, function(host, name) {
            that.$emit("uploadImage", {
              value: host + "/" + name,
            });
          });
        },
        randomString(len) {
          len = len || 32;
          var chars = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678";
          var maxPos = chars.length;
          var pwd = "";
          for (var i = 0; i < len; i++) {
            pwd += chars.charAt(Math.floor(Math.random() * maxPos));
          }
          return pwd;
        },
        getSuffix(filename) {
          var pos = filename.lastIndexOf(".");
          var suffix = "";
          if (pos !== -1) {
            suffix = filename.substring(pos);
          }
          return suffix;
        },
        b64toBlob(b64Data, contentType = "", sliceSize = 512) {
          const byteCharacters = atob(b64Data);
          const byteArrays = [];
    
          for (
            let offset = 0;
            offset < byteCharacters.length;
            offset += sliceSize
          ) {
            const slice = byteCharacters.slice(offset, offset + sliceSize);
    
            const byteNumbers = new Array(slice.length);
            for (let i = 0; i < slice.length; i++) {
              byteNumbers[i] = slice.charCodeAt(i);
            }
    
            const byteArray = new Uint8Array(byteNumbers);
    
            byteArrays.push(byteArray);
          }
    
          const blob = new Blob(byteArrays, { type: contentType });
          return blob;
        }
      }
    };
    </script>
    
    <style>
    </style>

    2.页面中引用组件

    <script>
    import uploadImg from '@/components/uploadImg'
    
    export default {
      data () {
        return {
          imgList: [],
        }
      },
      components: {
        uploadImg
      },
      methods: {
        uploadImage(val){
        // 将上传的图片放入数组中
          this.imgList.push(val.value)
        },
    }
    </script>
  • 相关阅读:
    并发编程三、线程可见性的底层原理
    并发编程二、线程的安全性和线程通信
    并发编程一、多线程的意义和使用
    Java进程监控
    分布式消息通信之RabbitMQ_Note
    分布式消息通信之RabbitMQ_02
    分布式消息通信之RabbitMQ_01
    分布式消息通信之RabbitMQ Tutorials
    SpringMVC重点分析
    Apache POI 4.0.1版本读取本地Excel文件并写入数据库(兼容 xls 和 xlsx)(五)
  • 原文地址:https://www.cnblogs.com/gqx-html/p/9963266.html
Copyright © 2011-2022 走看看