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

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

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

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

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

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

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

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

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

看到这里,有些小伙伴可能会说这有什么难的,虽然这个东西长相酷似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. PUN丨实用API

    原文地址:PUN丨实用API 当前房间人数 int num = PhotonNetwork.CurrentRoom.PlayerCount; 当前脚本是否属于当前玩家 //需继承MonoBehavio ...

  2. MySQL数据库快速入门与应用实战(阶段一)

    MySQL数据库快速入门与应用实战(阶段一) 作者 刘畅 时间 2020-09-02 实验环境说明: 系统:centos7.5 主机名 ip 配置 slavenode3 172.16.1.123 4核 ...

  3. flyway实现java 自动升级SQL脚本

    flyway实现java 自动升级SQL脚本 为什么要用Flyway 在日常开发中,我们经常会遇到下面的问题: 自己写的SQL忘了在所有环境执行: 别人写的SQL我们不能确定是否都在所有环境执行过了: ...

  4. Linux指令手册 (二)

    free free,显示系统中可用内存和已使用内存的数量. 语法:free [options] [target] 参数: -b: 以字节(bytes)显示内存量: -k: 以千字节(kilo)为单位显 ...

  5. Spring:Spring-IOC三种注入方式、注入不同数据类型

    一.Spring IOC(依赖注入的三种方式): 1.Setter方法注入 package com.jpeony.spring.setter; import com.jpeony.spring.com ...

  6. Java学习笔记之—Java基础

    将学习到的JAVA基础用xmind记录了下来,需要原件的可以私信

  7. MOS管开关电路笔记

    1.MOS管开关电路是利用MOS管栅极(g)控制MOS管源极(s)和漏极(d)通断的原理构造的电路.MOS管分为N沟道与P沟道,所以开关电路也主要分为两种.P沟道或N沟道共四种类型,但实际应用的只有增 ...

  8. kong插件Prometheus+grafana图形化展示

    目录 1. 准备工作 3. 为kong添加 prometheus插件 4. 打开kong的metrics支持 4. 配置prometheus.yml添加kong提供的数据信息 5. 在 Grafana ...

  9. 重新梳理调度器——GMP 调度模型

    调度器--GMP 调度模型 Goroutine 调度器,它是负责在工作线程上分发准备运行的 goroutines. 首先在讲 GMP 调度模型之前,我们先了解为什么会有这个模型,之前的调度模型是什么样 ...

  10. Django基础007--filter&tag

    1.Django自带的过滤器filter def index(request): print('index...........') navs = '今天天气真好fdsfds!!!' title='& ...