转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。

日常生活工作学习中,大家对电子表格必定不陌生。从工作数据汇总分析到出门收据各种电子发票,这些都是由电子表格制作出来的。

不过大家对电子表格的印象可能停留在这里:

标准行列数据统计的表格样式。

但其实,表格也可以是这样的:

工作中遇到需要实现的表格情况往往比大家想象的要更加复杂,最近我们在做客户支持的工作过程中遇到了一个客户,他需要借助电子表格表格实现合同中的电子签名。

电子签名通俗来说就是通过技术手段实现在电子文档上加载电子形式的签名,其作用类似于纸质合同上的手写签名或加盖的公章。在企业工作流审批、请柬、单据保全等场景应用广泛。

在经济活跃跨区域化现象越来越多的今天,作为电子表格的一个重要使用场景,电子合同可以实现异地签约,签署的时间第点更加自由;面对大批量的合同签署也可以轻松解决;同时传统纸质合同的管理更加方便,避免了纸质合同因保存管理问题而出现损坏。

而今天,客户在实际项目中需要实现的内容长这样:

看到这里,有些小伙伴可能会说这有什么难的,虽然这个东西长相酷似word,

但不就是电子表格去掉边框线吗?

如果只是简单的表格框内容,下段代码就可以简单的实现表格的绘制。

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

但是放大仔细看看,就会发现情况并不如我们所想的这么简单。

在这个合同中,我们除了要隐藏边框线,还要考虑边缘留白、图片跨越、页面滚动后截图不全等问题。 而借助电子表格在数据处理和分析方面天生具备的优势,可以很容易的实现电子签名功能。

我们今天就一起来尝试通过基于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画布,默认情况下不显示。

<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的那种效果。同时,也解决了我们在文章开头中提到缘留白、图片跨越、页面滚动后截图不全三个问题。

我们接下来还会为大家带来更多在工作项目中遇到的有趣内容。

来都来了,点个赞再走吧~

表格技术七十二变|手把手教你用Canvas电子表格做电子签名的更多相关文章

  1. 手把手教你用深度学习做物体检测(五):YOLOv1介绍

    "之前写物体检测系列文章的时候说过,关于YOLO算法,会在后续的文章中介绍,然而,由于YOLO历经3个版本,其论文也有3篇,想全面的讲述清楚还是太难了,本周终于能够抽出时间写一些YOLO算法 ...

  2. 手把手教你用深度学习做物体检测(六):YOLOv2介绍

    本文接着上一篇<手把手教你用深度学习做物体检测(五):YOLOv1介绍>文章,介绍YOLOv2在v1上的改进.有些性能度量指标术语看不懂没关系,后续会有通俗易懂的关于性能度量指标的介绍文章 ...

  3. 手把手教你用深度学习做物体检测(七):YOLOv3介绍

    YOLOv3 论文:< YOLOv3: An Incremental Improvement > 地址: https://arxiv.org/pdf/1804.02767.pdfyolov ...

  4. 【技术分享】手把手教你使用PowerShell内置的端口扫描器

    [技术分享]手把手教你使用PowerShell内置的端口扫描器 引言 想做端口扫描,NMAP是理想的选择,但是有时候NMAP并不可用.有的时候仅仅是想看一下某个端口是否开放.在这些情况下,PowerS ...

  5. 【转】手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)

    1.引言 特别说明:本文内容仅用于即时通讯技术研究和学习之用,请勿用于非法用途.如本文内容有不妥之处,请联系JackJiang进行处理!   我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...

  6. 手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)

    1.引言 特别说明:本文内容仅用于即时通讯技术研究和学习之用,请勿用于非法用途.如本文内容有不妥之处,请联系JackJiang进行处理!   我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...

  7. 手把手教你玩转 CSS3 3D 技术

    css3的3d起步 要玩转css3的3d,就必须了解几个词汇,便是透视(perspective).旋转(rotate)和移动(translate).透视即是以现实的视角来看屏幕上的2D事物,从而展现3 ...

  8. 手把手教你玩转CSS3 3D技术

    手把手教你玩转 CSS3 3D 技术   要玩转css3的3d,就必须了解几个词汇,便是透视(perspective).旋转(rotate)和移动(translate).透视即是以现实的视角来看屏幕上 ...

  9. 知识全聚集 .Net Core 技术突破 | 我用C#手把手教你玩微信自动化一

    知识全聚集 .Net Core 技术突破 | 我用C#手把手教你玩微信自动化一 教程 01 | 模块化方案一 02 | 模块化方案二 03 | 简单说说工作单元 其他教程预览 分库分表项目实战教程 G ...

随机推荐

  1. Linux 之 deb 包生成、安装、卸载

    Linux 之 deb 包的生成.安装和卸载 deb DEB 是 Debian 软件包格式的文件扩展名,是 Unixar 的标准归档,将包文件信息以及包内容,经过 gzip 和 tar 打包而成. d ...

  2. 12、Linux磁盘设备基础知识(2)

    12.4.计算磁盘容量: 磁盘的大小=盘面大小*磁头数 盘面的大小=磁道大小*磁道数 磁道大小=512字节*扇区数 磁盘的大小=512字节*扇区数*磁道数*磁头数 磁盘的大小=柱面大小*柱面数 柱面大 ...

  3. 1、centos7修改网卡名称为传统的eth0

    [root@localhost ~]# cd /etc/sysconfig/network-scripts/ [root@localhost network-scripts]#mv ifcfg-ens ...

  4. hdu 3306 Another kind of Fibonacci 矩阵快速幂

    参考了某大佬的 我们可以根据(s[n-2], a[n-1]^2, a[n-1]*a[n-2], a[n-2]^2) * A = (s[n-1], a[n]^2, a[n]*a[n-1], a[n-1] ...

  5. acwing 890. 能被整除的数

    #include<bits/stdc++.h> #define ll long long using namespace std; int m; int n,p[20]; int sum, ...

  6. Raspberry Pi:树莓派安装基础系统 Raspberry Pi(树莓派系统)

    准备材料 树莓派4B 树莓派系统镜像 SDFormatter (格式化工具) Win32DiskImager (镜像拷录工具) 镜像下载 Rspberry Pi (2020-08-24版本比较稳定) ...

  7. Mysql:mysql5.7长时间不连接失效问题

    问题 mysql5数据库连接超时问题:待机一晚上后,第二天早上第一次登录总是失败. 查看日志发现如下错误: "com.mysql.jdbc.exceptions.jdbc4.Communic ...

  8. docker进入容器所在虚拟机的指令

    sudo docker inspect -f {{.State.Pid}} 44fc0f0582d9 在拿到该进程PID之后我们就可以使用nsenter命令访问该容器了. $ sudo nsenter ...

  9. 20道Java实习生笔试面试选择题(内附答案解析)

    ​1.以下对继承的描述错误的是(A) A.Java中的继承允许一个子类继承多个父类 B.父类更具有通用性,子类更具体 C.Java中的继承存在的传递性 D.当实例化子类时会递归调用父类中的构造方法 解 ...

  10. 【论文小综】基于外部知识的VQA(视觉问答)

    ​ 我们生活在一个多模态的世界中.视觉的捕捉与理解,知识的学习与感知,语言的交流与表达,诸多方面的信息促进着我们对于世界的认知.作为多模态领域的一个典型场景,VQA旨在结合视觉的信息来回答所提出的问题 ...