需求:实现证件照上传时,提示用户证件照是否合法。
思路:在用户上传的照片上取三个像素点,判断像素点是否符合证件照的特点
项目中用到了element-plus中的el-upload 控件实现图片的上传,在实现此功能的过程中遇到了一系列的问题:
画布什么时候创建,创建的画布放在哪里...在画布里边拿不到原图的宽高等问题,经过多次尝试都已经解决。

首先创建一个画布(Canvas)

   <canvas id="myCanvas"  style="opacity: 0;" v-if='1'></canvas> 
  • 给存放证件照的img标签绑定id

     <el-upload
                      class="avatar-uploader"
                      ref='upload'
                      action="https://jsonplaceholder.typicode.com/posts/"
                             :show-file-list="false"
                             :on-success="handleAvatarSuccess"
                             :on-change="onChange"
                             :before-upload="beforeAvatarUpload"
                             :name='imgname'
                      style="
                           margin-top:19px;
                           width: 109px;
                           height: 136px;
                           text-align: center;
                           border: 2px dashed rgb(181, 181, 181);
                           text-align:center;
                           background-color:rgb(250, 250, 250)
                        "
                          >
                 <img  :src="imageUrl" class="avatar" style="width:110px;height:136px;" id='scream'>                                             
       </el-upload>
    

思考什么时候在把图片放到画布上比较好

  • 我这里是在,证件照上传之后,立即在画布上画出图片,在el-upload的onchange回调函数中进行,这样做思路没问题,但是onchange的调用时机(文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用),对此过程有影响,我们再添加文件时候已经调用了一次,这时候img里边还没有放东西,所以会报错。
  • 解决这个问题:
  • 我们可以使用一张图片来占用,我们提示用户的图标。(我这里一开始就给imageUrl绑定图片) 继续刚才的思路:

    var c=document.getElementById("myCanvas");

          var ctx=c.getContext("2d");
          var img=document.getElementById('scream')
          img.onload = function() {           
          var imgW= img.offsetWidth
          var imgH= img.clientHeight
          ctx.drawImage(img,0,0,imgW,imgH,0,0,imgW,imgH);
                                  }
    
  • 使用context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);剪切证件照,
  • 各参数的含义:

    img 规定要使用的图像、画布或视频。
    sx 可选。开始剪切的 x 坐标位置。
    sy 可选。开始剪切的 y 坐标位置。
    swidth 可选。被剪切图像的宽度。
    sheight 可选。被剪切图像的高度。
    x 在画布上放置图像的 x 坐标位置。
    y 在画布上放置图像的 y 坐标位置。
    width 可选。要使用的图像的宽度(伸展或缩小图像)。
    height 可选。要使用的图像的高度(伸展或缩小图像)。

    (参考菜鸟教程)

  • 这样处理看起来没问题,但是当我们接下来去取像素点的时候会发现,拿到的像素点并不是我们想要到,看一下img标签里边对图片的限制,显然,为了让图片在在页面上显示的更加美观,给用户一种良好的体验,我们需要对用户上传的大小不一的图片做一下限制,所以画布上画的并不是用户上传的图片。

为了拿到原图,解决思路:

  • 可以在定义一个和el-upload绑定相同URL的img标,把它画到画布里:

     <img  :src="imageUrl" class="avatar" id='scream1' style="opacity: 0;" >  
    
  • 接下来就只要拿到画布三个我们想要的像素点,就能解决问题了, 要求用户上传蓝底的证件照,我取的是左上角,右上角 和中间 三个点:
  ctx.drawImage(img,0,0,imgW,imgH,0,0,imgW,imgH);
   var rgb=ctx.getImageData(10,10,1,1).data;
  var rgb2=ctx.getImageData(imgW-10,10,1,1).data;
  var rgb3=ctx.getImageData(imgW/2+10,imgH/2-10,1,1).data;
  • 判断这三个点是否符合要求
  • 我是去每个点的rgb进行判断的,像素点颜色的范围,需要你自己去找你想要的的范围 onchange 里边的关键代码:
 onChange(file,fileList){
            //  判断图片内容
              var c=document.getElementById("myCanvas");
              var ctx=c.getContext("2d");
              var img=document.getElementById('scream1')
              var that=this
              img.onload = function() {           
                var imgW= img.offsetWidth
                var imgH= img.clientHeight
                ctx.drawImage(img,0,0,imgW,imgH,0,0,imgW,imgH);
                var rgb=ctx.getImageData(10,10,1,1).data;
                var rgb2=ctx.getImageData(imgW-10,10,1,1).data;
                var rgb3=ctx.getImageData(imgW/2+10,imgH/2-10,1,1).data;
                //左上角
                var rdata=rgb[0]
                var gdata=rgb[1]
                var bdata=rgb[2]
                // 右上角
                var rdata2=rgb2[0]
                var gdata2=rgb2[1]
                var bdata2=rgb2[2]
                   //中间
                var rdata3=rgb3[0]
                var gdata3=rgb3[1]
                var bdata3=rgb3[2]         
                 if( 0<=rdata && rdata<=79 &&
                     0 <= gdata && gdata <=218
                     &&240 <=bdata && bdata<=255
                     && 0<=rdata2 && rdata2<=79 
                     && 0<=gdata2 && gdata2<=218
                     &&240<=bdata2 && bdata2<=255
                     &&173<=rdata3 && rdata3<=244
                     && 180<=gdata3 && gdata3<=215&&
                     150<=bdata3 && bdata3<=187){
                    // 图片内容合法
                    this.abnrmal=0
                   window.localStorage.setItem('abnrmal',this.abnrmal)
                }else{
                    this.abnrmal=1
                    // 图片内容不合法
                    window.localStorage.setItem('abnrmal',this.abnrmal)
                    that.$message.error('请上传蓝底的证件照')
                    }
               }
         },

最后还有一个问题,就是千万不要有强迫症!!如果你一开始就把在画布组件上使用了,v-if / v-show 让图片不显示在页面上,那么就没办法进行了。

我们一开始随便在页面上操作,让这些东西消失在用户的视角,只需要最后,设置一下没用标签/组件的透明度(opacity)

 <canvas id="myCanvas"  style="opacity: 0;" ></canvas>
 <img  :src="imageUrl" class="avatar" id='scream1' style="opacity: 0;" > 

效果截图:

6.png

Last modification:August 2nd, 2021 at 07:55 pm
如果觉得我的文章对你有用,请随意赞赏