vue 移动端拍照压缩base64格式上传

时间:2023-01-25 18:07:52

啰嗦两句,因最近有个小项目要做一个拍照上传头像的功能,做的过程中出现了一些问题,针对这些问题做一下总结分享

问题:

  1.图片转base64

  2.手机拍照在ios和小米等手机下会旋转

  3.图片的压缩

  4.手机像素太大,进行一个等比缩放上传

啰嗦完了,上代码

  

<template>
  <div id="face">
    <div class="faceBox">
      <img src="" alt="" id="faceImg" ref="faceImg">
    </div>
    <p>请拍摄清晰的全部人脸信息以方便您的进场</p>
    <img src="../../static/images/example.png" alt="" class="example">
    <div class="startFaceBtn" v-show="!openVideo">
      <button class="startFace">开始拍摄</button>
      <input type="file" id="upimg" accept="image/*" @change="upLoad">
    </div>
    <button class="startFace" v-show="openVideo" @click="submit">开始上传</button>
  </div>
</template>

上面是页面的布局

关于处理图片旋转的问题需要使用 Exif

npm install exif-js

 

然后在main.js中引入

import EXIF from ‘exif-js‘
Vue.prototype.Exif = EXIF
<script>
import { Indicator } from ‘mint-ui‘;
export default {
  name: ‘face‘,
  data() {
    return {
      openVideo: false,
      imgUrl: null,
    }
  },
  mounted() {
  },
  methods: {
    upLoad(e) {
      let files = e.target.files || e.dataTransfer.files;
      if (!files.length) return;
      this.picavalue = files[0];
      console.log(this.picavalue.size / 1024);
      if (this.picavalue.size / 1024 > 10000) {
        this.$message({
          message: "图片过大不支持上传",
          type: "warning"
        });
      } else {
        this.imgPreview(this.picavalue);
      }
    },
    imgPreview(file, callback) {
      let that= this;
      let Orientation
//这里的Exif是判断图片旋转的
      that.Exif.getData(file, function () {
        Orientation = that.Exif.getTag(file, ‘Orientation‘);
      });
      if (!file || !window.FileReader) return;
      if (/^image/.test(file.type)) {
        let reader = new FileReader();
        reader.readAsDataURL(file)
        reader.onloadend = function() {
          let result = this.result;
          let img = new Image();
          img.src = result;
          img.onload = () => {
            let data = that.compress(img, Orientation);
            that.imgUrl = result;
            that.imgUrl = data
            console.log(data)
            that.$refs.faceImg.src = data
            that.openVideo = true
          };
        };
      }
    },
    compress(img, Orientation) {
      let canvas = document.createElement("canvas");
      let ctx = canvas.getContext("2d");
      let initSize = img.src.length;
      let width = img.width/3.5;
      let height = img.height/3.5;
      canvas.width = width;
      canvas.height = height;
      ctx.fillStyle = "#fff";
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      ctx.drawImage(img, 0, 0, width, height);
      console.log(Orientation)
//处理ios手机旋转角度问题
      if (navigator.userAgent.match(/iphone/i)) {  
        if(Orientation != "" && Orientation != 1){  
          switch(Orientation){  
          case 6:
            this.rotateImg(img,‘left‘,canvas);  
            break;  
          case 8: 
            this.rotateImg(img,‘right‘,canvas);  
            break;  
          case 3: 
            this.rotateImg(img,‘right‘,canvas);//转两次  
            this.rotateImg(img,‘right‘,canvas);  
            break;  
          }         
        }
      }else{ 
//处理其安卓类手机图片旋转的问题 
        if(Orientation != "" && Orientation != 1){   
          switch(Orientation){  
            case 6:
              this.rotateImg(img,‘left‘,canvas);  
              break;  
            case 8: 
              this.rotateImg(img,‘right‘,canvas);  
              break;  
            case 3: 
              this.rotateImg(img,‘right‘,canvas);
              this.rotateImg(img,‘right‘,canvas);  
              break;  
          }         
        }
      }
      // ndata 为base64格式的图片上传时可直接使用,根据清晰度的要求进行调整,这里我用的是0.4
      var ndata = canvas.toDataURL("image/jpeg", 0.4);
      return ndata;
    },
    rotateImg (img, direction,canvas) { 
      //最小与最大旋转方向,图片旋转4次后回到原方向 
      const min_step = 0; 
      const max_step = 3; 
      if (img == null)return; 
      //img的高度和宽度不能在img元素隐藏后获取,否则会出错 
      //这里因为图片像素太大进行了一个3.5倍的缩放 
      let height = img.height/3.5; 
      let width = img.width/3.5; 
      let 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); 
      } 
      //旋转角度以弧度值为参数 
      let degree = step * 90 * Math.PI / 180; 
      let ctx = canvas.getContext(‘2d‘);
      console.log(step)
      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; 
      } 
    },
    submit() {
      //点击按钮处理上传图片的逻辑就行了,这里就不做介绍了
} } }
</script>

文章参照:https://blog.csdn.net/xiaogezl/article/details/70156500