1. 程式人生 > >手寫簽名外掛—jSignature使用心得

手寫簽名外掛—jSignature使用心得

    最近需要做一個移動端手寫簽名的功能,上網搜了一下基本都是jSignature這個外掛,幾乎沒得第二選擇,於是照著網上的各個版本copy測試,在PC端測試是沒什麼問題的,很easy。

    問題1::在移動端改變了canvas的父盒子大小後就出現問題了,手寫的和顯示的不在一起,jSignature畫筆出現了偏移,經過審查元素髮現,是由於canvas的尺寸大小變成了100%引起的,解決辦法就是需要手動設定canvas的尺寸,如果用100%、rem這些相對單位是會出現問題的,如果需要做響應式的,那麼就在媒體查詢裡面寫,如果需要用js控制,需設定canvas.attr(“width”,”200”),注意不要帶單位!!

,結論:style裡的寬高和canvas標籤裡的寬高要對應,不然筆的位置就出現偏差;

    問題2:由於移動端有高倍屏,所以出現了畫布筆畫模糊的問題,這就需要根據螢幕的DPI來更改畫布的大小,普通螢幕設定style=”width:300px;height:150px;” 屬性裡設定width=”300” height=”150”,在高清屏時style的寬高不變,canvas裡的width=”300*DPI” heigth=”150*DPI”,這樣就清晰了,好在已經有前輩封裝好了,hidpi-canvas.js直接拿來用即可。

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

    問題3:落筆不夠圓滑的問題,由於設定了畫筆的寬度為10px,當點在螢幕上時顯示的不是一個點,而是一個方塊,一個10*10px的方塊,已經看到有大神寫了demo出來了,應該是用react寫的,暫時還沒有研究出來移植到我的程式碼中,參考地址:canvas簽名元件,不過外觀和自適應螢幕這塊作者可能沒有做很多處理,還需要自己再加工;

    問題4:簽名沒有筆鋒,也就是沒有原筆跡的那種效果,這個可真難到我了,畢竟牽涉到很多演算法,不像是一筆畫下去那麼簡單了,原以為web端實現幾乎不可能,但還是有國外的高手幾年前就寫了demo了,正因為是高手寫的,看起來也很費勁,檔案層層引用,一個簽名的頁面請求的檔案38個之多,想要拿過來用都很難,有興趣的可以研究一下並分享哦!

    下面是簽名顯示及上傳到阿里雲OSS程式碼,有需要的可以看看,如果只是需要看jSignature的引數,百度搜索簡單版的看吧。

<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>