表格技術七十二變|手把手教你用Canvas電子表格做電子簽名

葡萄城技術團隊發表於2021-08-11

轉載請註明出處:葡萄城官網,葡萄城為開發者提供專業的開發工具、解決方案和服務,賦能開發者。

日常生活工作學習中,大家對電子表格必定不陌生。從工作資料彙總分析到出門收據各種電子發票,這些都是由電子表格製作出來的。

不過大家對電子表格的印象可能停留在這裡:

image

標準行列資料統計的表格樣式。

但其實,表格也可以是這樣的:

image

工作中遇到需要實現的表格情況往往比大家想象的要更加複雜,最近我們在做客戶支援的工作過程中遇到了一個客戶,他需要藉助電子表格表格實現合同中的電子簽名。

電子簽名通俗來說就是通過技術手段實現在電子文件上載入電子形式的簽名,其作用類似於紙質合同上的手寫簽名或加蓋的公章。在企業工作流審批、請柬、單據保全等場景應用廣泛。

在經濟活躍跨區域化現象越來越多的今天,作為電子表格的一個重要使用場景,電子合同可以實現異地簽約,簽署的時間第點更加自由;面對大批量的合同簽署也可以輕鬆解決;同時傳統紙質合同的管理更加方便,避免了紙質合同因儲存管理問題而出現損壞。

而今天,客戶在實際專案中需要實現的內容長這樣:

6.png

看到這裡,有些小夥伴可能會說這有什麼難的,雖然這個東西長相酷似word,

但不就是電子表格去掉邊框線嗎?

image

如果只是簡單的表格框內容,下段程式碼就可以簡單的實現表格的繪製。

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <title>02Canvas案例-繪製表格</title>

</head>

<body>

<div id="container">

    <canvas id="cavsElem">

        

    </canvas>

</div>

<script>

    (function(){

        var canvas=document.querySelector('#cavsElem');

        var ctx=canvas.getContext('2d');

        canvas.width=600;

        canvas.height=600;

        canvas.style.border='1px solid green';

        var rectH=10;

        var rectW=20;

        ctx.lineWidth=.5;

        //繪製表格

        // 第一步: 繪製橫線

        for(var i=0;i<canvas.width;i++){

            ctx.moveTo(rectW*i,0);

            //如果不設定moveTo,當前畫筆沒有位置

            ctx.lineTo(rectW*i,canvas.height);

        }

        //第二步:繪製豎線:如果繪製的格子的寬高相等,可以將for迴圈放到一個裡面;

        for(var i=0;i<canvas.height;i++){

            ctx.moveTo(0,rectH*i);

            ctx.lineTo(canvas.width,rectH*i);

        }

        ctx.stroke();

    }())

</script>

</body>

</html>

但是放大仔細看看,就會發現情況並不如我們所想的這麼簡單。

image

image

image

在這個合同中,我們除了要隱藏邊框線,還要考慮邊緣留白、圖片跨越、頁面滾動後截圖不全等問題。 而藉助電子表格在資料處理和分析方面天生具備的優勢,可以很容易的實現電子簽名功能。

我們今天就一起來嘗試通過基於Canvas的電子表格來實現電子簽名並匯出PDF的專案開發需求。

實現思路

環境準備

1. 環境準備:安裝SpreadJS 前端表格外掛,並通過外掛繪製canvas畫布。

  1. 初始化Spread工作簿,並匯入合同模板

  2. 建立Canvas畫布並引用esign.js畫法實現手寫簽名區域

  3. 通過自定義超連結跳轉命令,簽名區域撥出

  4. 將簽名區域轉化為圖片設定為背景圖片

  5. 使用SpreadJS提供的匯出PDF介面將簽署的檔案匯出

電子簽名的實現

初始化Spread工作簿

1、引入以下檔案

<link rel="stylesheet" type="text/css" href="node_modules/@grapecity/spread-sheets/styles/gc.spread.sheets.excel2013white.css">

<script src="node_modules/@grapecity/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script>

<script src="new2.ssjson" type="text/javascript"></script>

1、建立用於承載SpreadJS的DOM

<div id="ss" class="sample-spreadsheets" style="height: 900px;">

2、用JS獲取DOM物件並進行初始化

var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"));

3、匯入合同模板

spread.fromJSON(str);

到這裡,我們Spread工作簿已經初始化完成了。當然,你也可以新增對應的CSS調整表單的大小。

關於模板的製作,你可以在線上表格編輯器中根據需求進行繪製,並匯出為ssjson檔案並通過fromJSON匯入到我們的表單中。

接下來,用Canvas畫布來實現手寫簽名區域。

手寫簽名區域

1、首先,我們先建立簽名區域的DOM元素,並定義一個Canvas畫布,預設情況下不顯示。

4.png

<div class="containter" id="box" style="display: none;">

       <div class="canvasDiv">

             <div id="editing_area">

                  <canvas id="canvasEdit"></canvas>

             </div>

       </div>

       <div class="btnDiv">

             <a id="sign_clear" class="clearBtn">清空</a>

             <a id="sign_clear2" class="clearBtn">簽署</a>

       </div>

</div>

2、引用esign.js和jQuery。Esign.js是一種用滑鼠在canvas上繪製的畫法。

`

`

3、初始化
`
$(document).esign("canvasEdit", "sign_show", "sign_clear", "sign_ok");

$(document).on('click', '#sign_clear2', takeScreenshot);`

Canvas畫布中利用自定義單元格,理論上也是能開發出能夠直接簽名的單元格。

使用者可以直接在單元格進行簽名,有興趣的小夥伴可以嘗試用自定義單元格實現。

自定義超連結命令

1、建立超連結

sheet.setValue(32, 10, "稽核人簽名:")

sheet.setHyperlink(32, 10, { command: "popup" });

2、為超連結設定命令,點選彈出畫布

spread.commandManager().register("popup",{

                    canUndo: true,

                    execute: function (context, options, isUndo) {

                    var Commands = GC.Spread.Sheets.Commands;

                    // 在此加cmd

                    options.cmd = "popup";

                    if (isUndo) {

                           Commands.undoTransaction(context, options);

                                  return true;

                           } else {

                                  Commands.startTransaction(context, options);

 

                                 document.getElementById("box").style.display = "block";

 

                                  Commands.endTransaction(context, options);

                                        return true;

                                  }

                           }

                });

指定DOM轉為圖片並設定為單元格背景

1、利用canvas的介面,將畫布轉為base64,呼叫介面設定背景

function convertCanvasToImage(canvas) {

                    return canvas.toDataURL("image/png");

   };

 

  function takeScreenshot() {       

      var canvas = document.getElementById("canvasEdit");

      var imgUrl = convertCanvasToImage(canvas); //擷取圖片路徑,該路徑為伺服器引數

      var sheet = spread.getSheet(0); 

      sheet.getCell(32,13).backgroundImage(imgUrl);

      sheet.getCell(35,13).backgroundImage(imgUrl);

      sheet.getCell(38,13).backgroundImage(imgUrl);

}

2、關閉簽名畫布


function tishi(){

      document.getElementById("box").style.display = "none";

}

setTimeout(tishi,100)

將電子簽名匯出PDF

上面已經實現了電子簽名內容,但是我們都知道合同需要有列印輸出功能,接下來我們繼續介紹如何使用pdf列印輸出電子簽名。

1、引用PDF擴充檔案以及filesaver

<script src="node_modules/@grapecity/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js" type="text/javascript"></script>

<script src="node_modules/file-saver/dist/FileSaver.min.js" type="text/javascript"></script>

1、呼叫介面匯出PDF

spread.savePDF(function (blob) {

    var fileName = 'download';

    saveAs(blob, fileName + '.pdf');

}, function (error) {

    console.log(error);

}, {

    title: 'Test Title',

});

注意:匯出中文字元需要註冊對應的字型。


總結

以上,我們實現了基於Canvas電子表格實現電子簽名並使用PDF匯出列印的完整功能,由於Canvas完全取代了頁面的dom結構,因此列印時不需要遍歷要列印的dom節點的子節點,也不必將每一頁所能列印的dom節點高度累加,這樣做可以不用再計算dom節點的高度,大幅節省了系統效能,同時實現了較細的頁面顆粒度,不會造成大塊空白的情況,完全模擬出了word生成pdf的那種效果。同時,也解決了我們在文章開頭中提到緣留白、圖片跨越、頁面滾動後截圖不全三個問題。
image

我們接下來還會為大家帶來更多在工作專案中遇到的有趣內容。

來都來了,點個贊再走吧~

相關文章