Handwritten Signature Plugin—jSignature Experience

    Recently, I need to do a function of handwritten signature on the mobile terminal. I searched on the Internet and basically found the plug-in jSignature. There is almost no second choice. .

    Question 1: : The problem occurred after the mobile terminal changed the size of the parent box of the canvas. The handwritten and displayed ones were not together, and the jSignature brush was offset. After reviewing the elements, it was found that the size of the canvas became 100. %, the solution is to manually set the size of the canvas. If you use relative units such as 100% and rem, there will be problems. If you need to be responsive, then write it in the media query. If you need to use js control, Need to set canvas.attr("width","200"), be careful not to bring units! ! , Conclusion: The width and height in the style should correspond to the width and height in the canvas tag , otherwise the position of the pen will deviate;

    Question 2: Due to the high magnification screen on the mobile terminal, there is a problem of blurred canvas strokes. This requires changing the size of the canvas according to the DPI of the screen. For ordinary screens, set style=”width:300px;height:150px;” in the property width=”300” height=”150”, the width and height of the style in the high-definition screen remain unchanged, the width=”300*DPI” height=”150*DPI” in the canvas , so it is clear, fortunately there are already predecessors Once packaged, hidpi-canvas.js can be used directly.

<script src="js/hidpi-canvas.js"></script>
<script src="js/signature/jSignature.js" ></script>

    Question 3: The pen is not smooth enough. Since the width of the brush is set to 10px, when the point is on the screen, it is not a point, but a square, a 10*10px square. I have seen that a great god wrote a demo. It came out, it should be written in react, and I haven't researched it and transplanted it into my code. Reference address: canvas signature component , but the author may not have done a lot of processing on the appearance and adaptive screen, and needs to reprocess it by himself;

    Question 4: The signature does not have a stroke, that is, it does not have the effect of the original handwriting. This is really difficult for me. After all, it involves a lot of algorithms. It is not as simple as drawing a single stroke. But there are still foreign masters who wrote demos a few years ago. Because they are written by masters, it seems very laborious. The files are referenced layer by layer. A signed page requests as many as 38 files. I want to use it. It's very difficult, if you are interested, you can study it and share it!

    GitHub project name: sign-here
    canvas original handwriting signature demo

    The following is the signature display and upload to Alibaba Cloud OSS code, you can take a look if you need it. If you only need to see the parameters of jSignature, you can look at the simple version of Baidu search.

<script type="text/javascript">     
        $(function () {
            $.ajaxSetup({
                async:false
            });
            window.canvasIsEmpty = "Y"//用于判断是否有手写签名,默认是空,无签名.jSignature.js中开启画笔后就会改变这个值。
            var sigdiv = $("#signature");
            sigdiv.jSignature('init',{height:'100%',width:'100%',color:"#000",lineWidth:10});

            $("#closeSign").on("click",function(){
                reset();                
                $("#signWrap").removeClass("flex disable-touch");
            });

            //点击签名的图片和提示文字弹出签名的画板
            $("#imageViewBox").on("click","#user_sign_img,#user_sign_tips",function(){
                 getOSSAuth();
                 $("#loadingStatus").css({"width":"0"});//进度条置零
                 $("#loadingStatus span").text("");//清除进度显示文字
                 $("#signWrap").addClass("flex disable-touch");                 
            });

            //清除历史签名,从OSS上删除
            $("#imageViewBox").on("click","#user_sign_delete",function(){
                $.post("OSSAuth/yjsigndel.shtml",{basename:basename},function(res){
                    layer.msg("电子签名已删除");
                    $("#user_sign_img").attr("src","image/sign_img_default.jpg");
                    $("#user_sign_delete").hide();
                    $("#user_sign_tips").show();
                })
            })

            $("#myShare,#myPatient,#mySst,.store,.sign-in-day").on("click",function(){layer.msg("敬请期待")})

        });

        function reset() {
            var $sigdiv = $("#signature");
            $sigdiv.jSignature("reset");
            if(window.canvasIsEmpty === "Y"){$("#signWrap").removeClass("flex");}
            window.canvasIsEmpty = "Y";
        }

        //监听签名动作,并显示预览
        function jSignature_img() {
            if(window.canvasIsEmpty === "Y"){
                layer.msg("请签名");
                return false;
            } 
            var $sigdiv = $("#signature");
            var datapair = $sigdiv.jSignature("getData", "image"); //设置输出的格式,具体可以参考官方文档
            var i = new Image();
            i.src = "data:" + datapair[0] + "," + datapair[1];
            i.crossOrigin="anonymous";
            $("#user_sign_img").attr("src",i.src);
            $("#user_sign_tips").hide();

            //封装blob对象  
            var blob = convertBase64UrlToBlob(i.src); 
            upload(blob)
        }

        function convertBase64UrlToBlob(urlData){
            var bytes=window.atob(urlData.split(',')[1]);        //去掉url的头,并转换为byte
            //处理异常,将ascii码小于0的转换为大于0
            var ab = new ArrayBuffer(bytes.length);
            var ia = new Uint8Array(ab);
            for (var i = 0; i < bytes.length; i++) {
                ia[i] = bytes.charCodeAt(i);
            }
            return new Blob( [ab] , {type : 'image/png'});
        }

       /* 图片上传 */ 
       var hostUrl=window.location.protocol+"//"+window.location.host+"/yunjingservice/"; 
       var basename=Base64.encodeURI("${user_name}");       
       var accessid='',policy='', Signature='', key='signature/${user_id.substring(0, 4)}_'+basename+'.png' ,host='',expire = 0,now = 0;

       // 可以判断当前expire是否超过了当前时间,如果超过了当前时间,就重新取一下,3s 做为缓冲
       function getOSSAuth(){
          now = Date.parse(new Date()) / 1000; 
          if (expire < now + 3){
               $.post(hostUrl + "OSSAuth/yjsign.shtml",{dir:"signature"},function(data){
                console.dir(data);
                accessid=data.accessid;
                policy=data.policy;
                signature=data.signature;
                expire=data.expire;
                host=data.host;
              });
           }
       }

      function get_suffix(filename) {
        pos = filename.lastIndexOf('.')
        suffix = ''
        if (pos != -1) {
            suffix = filename.substring(pos)
        }
        return suffix;
      }

       function upload(blob){
         getOSSAuth();//获取授权
         var request = new FormData(); 
           request.append('OSSAccessKeyId', accessid);
           request.append('policy', policy);
           request.append('Signature',signature);
           request.append('key',key);//+filename
           request.append('success_action_status','200');//status头,如果不设置返回的是204
           request.append('Access-Control-Allow-Origin','*');
           request.append('Access-Control-Allow-Methods','GET, POST');
           //request.append('file', $(".upload_input")[0].files[0]);
           request.append("fileData", blob);//fileData为自定义 
           request.append('file', blob);
           request.append("imageName",blob);
           $.ajax({
               url: host,
               data: request,
               processData: false,
               cache: false,
               async: false,
               contentType: false,
               //关键是要设置contentType 为false,不然发出的请求头 没有boundary
               type: "POST",
               beforeSend:function(){
                 var width = 1;
                  timer = setInterval(function(){
                    $("#loadingStatus").css({"width":width + "%"});
                    $("#loadingStatus span").text("上传中"+width+"%")
                    width++;
                    if(width == 98){
                        clearInterval(timer)
                    }
                 },34)
               },
               success: function (data,textStatus, request) {
                 console.log(data)
                 if (request.status == '200') {
                     reset();
                     clearInterval(timer)
                     $("#loadingStatus").css({"width":"100%"});
                     //$("#imageViewBox").css({"height":"auto"})
                     $("#signWrap").removeClass("flex");
                     $("#user_sign_delete").show();
                     layer.msg('签名保存成功!');
                 }
               },
               error: function (data,textStatus, request) {
                   layer.msg('上传失败,请重试!');
               },
               complete:function(){
               }
           });
       }

        var signImgSrc = "https://biangene.oss-cn-shenzhen.aliyuncs.com/signature/${user_id.substring(0, 4)}_"+basename+".png";

        $(function(){
            var time = Date.parse(new Date());
           $("#user_sign_img").attr("src","https://biangene.oss-cn-shenzhen.aliyuncs.com/signature/${user_id.substring(0, 4)}_"+basename+".png?"+time);
        });

        $(window).load(function(){
           $("img.user_sign").each(function() {
               if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) { 
                  $("#user_sign_img").attr("src","image/sign_img_default.jpg").show();
                  $("#user_sign_tips").show();
                  $("#user_sign_delete").hide();
               }else{
                  $("#user_sign_img").show()
                  $("#user_sign_tips").hide();
                  $("#user_sign_delete").show();
               }
           });

    });  

   </script>

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325568361&siteId=291194637