H5端 图片裁剪插件cropperjs和vue-cropper

史骏
2023-12-01

使用vue-cropper (https://github.com/xyxiao001/vue-cropper)移动端情况下裁剪的时候 会出现部分机型图片翻转以及拖动卡顿问题,直接改源码, 图片翻转问题可以解决在checkOrientationImage方法中注释掉h.rotate(90 * Math.PI / 180) 即可。卡拖动顿问题 在 moveImg startMove 方法中加上 t.stopImmediatePropagation() 本地调试二次打开的时候出现卡死现象,lssues中也未能解决,谷歌百度了一天也没找到方法。。

最后更换了插件:https://github.com/fengyuanchen/cropperjs 

中文文档说明 :cropperjs实践及中文文档(自译) - 灭灭 - 博客园

中间也踩了坑,但是都解决啦

业务中需要上传裁剪后的图片识别身份证上的信息,这里必须这样写,不然得到的64格式图片会模糊不清导致识别不了。

_this.url = _this.cropper.getCroppedCanvas({
            imageSmoothingQuality: 'high'
          }).toDataURL('image/jpeg')

mounted中先实例化裁剪框:

   var self = this;
    var image = document.getElementById("image");
    self.cropper = new Cropper(image, {
      aspectRatio: 304/190,
      viewMode: 1,
      dragMode :"move",
      zoomable: false,
      ready: function () {
        self.croppable = true;
      },
    });

直接上代码

<template>
<div id="scan_idcard">
  <van-nav-bar title="扫描身份证" left-arrow @click-left="onClickLeft"></van-nav-bar>
	<div class="container">
    <div style="padding: 0 12px">
      <label for="uploads" class="base_content">
        <van-uploader v-model="frontImg1" :after-read="uploadFront" deletable  @delete="delImg('frontImg1')" :max-count="1">
          <van-button>
            <img v-show="frontImg1.length == 0" src="_pic_03.png">
          </van-button>
          
        </van-uploader> 
        <!-- <img v-tap="[uploadImg,'frontImg1']" v-show="!frontImg1" src="pic_03.png">
        <img v-tap="[uploadImg,'frontImg1']" v-show="frontImg1" :src="frontImg1"> -->
      </label>
      <label for="upload" class="base_content">
        <van-uploader v-model="frontImg2" :after-read="uploadBack" deletable @delete="delImg('frontImg2')" :max-count="1">
          <van-button>
            <img v-show="frontImg2.length == 0" src="e/yancheng_pic_04.png">
          </van-button>
        </van-uploader>
        <!-- <img v-tap="[uploadImg,'frontImg2']" v-show="!frontImg2" src="ancheng_pic_04.png">
        <img v-tap="[uploadImg,'frontImg2']" v-show="frontImg2" :src="frontImg2"> -->
      </label>
      <div class="btn" v-tap="[submit]">提交</div>
    </div>

    <div class="dialog"
      v-show="showCropperDialog"
      >
      <div>
        <img style="max-width: 100%;" id= "image" :src="url" alt="Picture" >
      </div>
      <div class="upload-btn">
        <!-- <van-button type="default" @click="changeScale(-1)">缩小</van-button>
        <van-button type="info" @click="changeScale(1)">放大</van-button> -->
        <van-button class="btn1" type="default" @click="cancleUpload">取消</van-button>
        <van-button class="btn2" type="info" @click="uploadCropImg">确认</van-button>
      </div>
    </div>
	</div>
</div>
</template>
<script>
import Util from "../../assets/js/util";
import wx from 'weixin-js-sdk';
import Cropper from "cropperjs";
import "cropperjs/dist/cropper.css";
  export default {
    inject: ['reload'],
    data() {
      return {
        frontImg1:[],   //身份证正面照
        frontImg2:[],   //身份证反面照
        //剪切图片上传
        crap: false,
        previews: {},
        imgFile:"",
        fileName:'',  // 本机文件地址
        showCropperDialog:false,
        user_name:"",  //姓名
        user_nation:"",  //民族
        user_idcard_no:"", //身份证号
        user_sex:"",    //性别
        user_birthday:"",  //生日
        user_idcard_address:"" , //身份证地址


        headerImage: "",
      picValue: "",
      cropper: "",
      croppable: false,
      panel: false,
      url: "",
      };
    },
    mounted() {
      this.imgOnload()
       var self = this;
    var image = document.getElementById("image");
    self.cropper = new Cropper(image, {
      aspectRatio: 304/190,
      viewMode: 1,
      dragMode :"move",
      zoomable: false,
      ready: function () {
        self.croppable = true;
      },
    });

    },
    created() {
    },
    methods: {

    
    getObjectURL(file) {
      var url = null;
      if (window.createObjectURL != undefined) {
        // basic
        url = window.createObjectURL(file);
      } else if (window.URL != undefined) {
        // mozilla(firefox)
        url = window.URL.createObjectURL(file);
      } else if (window.webkitURL != undefined) {
        // webkit or chrome
        url = window.webkitURL.createObjectURL(file);
      }
      return url;
    },
      onClickLeft(){
        this.$router.go(-1);
        window.localStorage.removeItem('imageinfo1')
        window.localStorage.removeItem('imageinfo2')
      },
      // 提交
      submit(){
        let _this = this;
        let data = {
          frontImg1 : _this.frontImg1[0].url,
          frontImg2 : _this.frontImg2[0].url,
          user_name : _this.user_name,
          user_nation : _this.user_nation,
          user_idcard_no : _this.user_idcard_no,
          user_sex : _this.user_sex,
          user_birthday : _this.user_birthday,
          user_idcard_address : _this.user_idcard_address,
        };
        console.log('555',data);
        Util.$emit("idCardInfo", data);
        _this.$router.go(-1);
        window.localStorage.removeItem('imageinfo1')
        window.localStorage.removeItem('imageinfo2')

      },
      // 放大/缩小
      changeScale(num) {
        num = num || 1;
        this.$refs.cropper.changeScale(num);
      },
      cancleUpload(){    //取消裁剪
      let that = this 
        that.url = ""
        that.showCropperDialog = false
        
      },

      imgOnload(){
        let _this = this
        let res1 = JSON.parse(window.localStorage.getItem("imageinfo1"))
        let res2 = JSON.parse(window.localStorage.getItem("imageinfo2"))
        if(res1){
        if(res1.info == "success"){
                let img = {
                  url:res1.data.dir
                }
                _this.frontImg1.push(img);   //身份证正面照
                _this.user_name = res1.data.idcard.name;   姓名
                _this.user_nation = res1.data.idcard.nation;   民族
                _this.user_idcard_no = res1.data.idcard.id;   //身份证号
                _this.user_sex = res1.data.idcard.sex;   //性别
                _this.user_birthday = res1.data.idcard.birth;   //生日
                _this.user_idcard_address = res1.data.idcard.address;   //身份证地址
        }}
        if(res2){
         if (res2.info == "success"){
              let img = {
                  url:res2.data.dir
                }
                _this.frontImg2.push(img);   //身份证正面照
        }}
      },

      getBase64Image(img) { 
     var canvas = document.createElement("canvas"); 
     canvas.width = img.width; 
     canvas.height = img.height; 
     var ctx = canvas.getContext("2d"); 
     ctx.drawImage(img, 0, 0, img.width, img.height); 
     var ext = img.src.substring(img.src.lastIndexOf(".")+1).toLowerCase(); 
     var dataURL = canvas.toDataURL("image/"+ext); 
     return dataURL; 
} ,
      // 上传剪切后图片
      uploadCropImg () {
        let _this = this;
        if(this.upload_type === 'frontImg1') {
          // 隐藏裁剪图片弹窗
           _this.url = _this.cropper.getCroppedCanvas({
            imageSmoothingQuality: 'high'
          }).toDataURL('image/jpeg')
          _this.showCropperDialog = false;
            _this.Toast.loading({
              duration: 0, // 持续展示 toast
              forbidClick: true,
              message: '上传中...',
            });
            _this.$ajax()
            .post("/wechat/auth/base64Upload",{
              card_type: 0,
              file:_this.url,
            })
            .then(function(response){
              let res = response.data;
              console.log('res',res);
              _this.Toast.clear();
              if(res.status == 1){
                let img = {
                  url:res.data.dir
                }
            _this.url = ""

                _this.frontImg1.push(img);   //身份证正面照
                if(!res.data.idcard.name){
                  _this.Toast("识别失败,请重新扫描!")
                  return false
                }
                _this.user_name = res.data.idcard.name;   姓名
                if(!res.data.idcard.name){
                  _this.Toast("识别失败,请重新扫描!")
                  return false
                }
                _this.user_nation = res.data.idcard.nation;   民族
                if(!res.data.idcard.nation){
                  _this.Toast("识别失败,请重新扫描!")
                  return false
                }
                _this.user_idcard_no = res.data.idcard.id;   //身份证号
                if(!res.data.idcard.id){
                  _this.Toast("识别失败,请重新扫描")
                  return false
                }
                _this.user_sex = res.data.idcard.sex;   //性别
                if(!res.data.idcard.sex){
                  _this.Toast("识别失败,请重新扫描!")
                  return false
                }
                _this.user_birthday = res.data.idcard.birth;   //生日
                if(!res.data.idcard.birth){
                  _this.Toast("识别失败,请重新扫描!")
                  return false
                }
                _this.user_idcard_address = res.data.idcard.address;   //身份证地址
                if(!res.data.idcard.address){
                  _this.Toast("识别失败,请重新扫描!")
                  return false
                }
                window.localStorage.setItem("imageinfo1",JSON.stringify(res))
              }else{
            _this.url = ""
                _this.Toast(res.info)
              }
            })

           
          // })
        }else if(this.upload_type === 'frontImg2') {
          // 隐藏裁剪图片弹窗
           _this.url = _this.cropper.getCroppedCanvas({
            imageSmoothingQuality: 'high'
          }).toDataURL('image/jpeg')
          _this.showCropperDialog = false;
            _this.Toast.loading({
              duration: 0, // 持续展示 toast
              forbidClick: true,
              message: '上传中...',
            });
            _this
            .$ajax()
            .post("/wechat/auth/base64Upload",{
              card_type: 1,
              file:_this.url,
            })
            .then(function(response){
              let res = response.data;
              _this.Toast.clear();
              if(res.status == 1){
                let img = {
                  url:res.data.dir
                }
                _this.frontImg2.push(img);   //身份证反面照
                window.localStorage.setItem("imageinfo2",JSON.stringify(res))
                _this.url = ""

              }else{
                  _this.url = ""
                _this.Toast(res.info)
              }
            })
        }
      },
      
      uploadFront(file){ //上传身份证正面照片
        let _this = this;
        _this.url = file.content;
   
        _this.frontImg1 = [];
        _this.upload_type = 'frontImg1';   //当前上传的是身份证正面还是反面
        _this.showCropperDialog = true;    //显示裁剪框
        //每次替换图片要重新得到新的url
        // if (_this.cropper) {
          _this.cropper.replace(_this.url);
        // }
      },
      uploadBack(file){ //上传身份证反面照片
        let _this = this;

        _this.url = file.content;
        _this.frontImg2 = [];
        _this.upload_type = 'frontImg2';   //当前上传的是身份证正面还是反面
        _this.showCropperDialog = true;    //显示裁剪框
        //每次替换图片要重新得到新的url
          _this.cropper.replace(_this.url);
      },
      delImg(item){ //删除图片
        this[item] = [];
        window.localStorage.removeItem('imageinfo1')
        window.localStorage.removeItem('imageinfo2')

      },
    },
    components: {

    },
  };
</script>
<style lang="less" type="text/less">
  .dialog{
    z-index: 99;
    position: fixed;
    padding-top: 60px;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 1);
  }
  .btn1{
        margin-left: 6%;
    margin-top: 10px;
  }
  .btn2{
        margin-left: 52%;
  }
  
  #scan_idcard {
    background-color:#FFFFFF;
    overflow: scroll;

    .van-uploader{
      .van-button--default{
        padding: 0;
        border: none;
        height: 100%;
      }
    }
    .van-uploader,.van-uploader__wrapper{
      width: 100%;
    }
    .van-uploader__preview{
      width: 100%;
      margin: 0;
    }
    .van-uploader__preview-image{
      width: 100%;
      height: auto;
    }
    .van-dialog{
      display: flex;
      align-items: center;
      top:0;
      left: 0;
      width: 100%;
      bottom: 0;
      transform: none;
      background-color: inherit;
      .van-dialog__content{
        width: 100%;
        height: 400px;
        .cropper-view-box{
          outline: 1px solid #FFFFFF;
        }
        .crop-info{
          display: none;
        }
      }
      .upload-btn{
        display: flex;
        padding: 30px 30px 0;
        justify-content: space-between;
      }
    }
    .base_content{
      img{
        display: block;
        width: 100%;
        height: 221px;
        overflow: hidden;
        margin-bottom: 10px;
      }
    }
    .btn{
      margin-top:30px;
      border-radius: 20px;
    }
  }
</style>

 类似资料: