如何通过canvas实现电子签名
想要实现一个电子签名,可以支持鼠标签名,还能类似书法效果线条有粗有细,同时可以导出成图片.
一、实现连贯的划线
1)首先需要注册鼠标下压、鼠标放开、鼠标移出和鼠标移动事件,通过鼠标下压赋值downFlag标记开始绘制
2) 鼠标移动时,将当前坐标位置传入绘制方法,通过lineTo方法实现绘制
/**
* 按下鼠标启动绘制标记
**/
canvas.addEventListener('mousedown', e => {
preCoord = [e.offsetX, e.offsetY, new Date().getTime()];
downFlag = true;
}) /**
* 鼠标松开结束绘制
**/
canvas.addEventListener('mouseup', e => {
downFlag = false;
})
canvas.addEventListener('mouseout', () => {
downFlag = false;
}) /**
* 鼠标移动时绘制文字
**/
canvas.addEventListener('mousemove', e => {
if (downFlag) {
const coord = [e.offsetX, e.offsetY];
drawSign(coord);
preCoord = [...coord, new Date().getTime()];
}
})
3) 启动线的绘制,其中注释的线段
function drawSign(coord) {
// 为了实现阶段性线的不同粗细程度,所以每次绘制必须重新开始一段路径
ctx.beginPath();
getColor(coord);
ctx.lineTo(...preCoord);
ctx.lineTo(...coord);
ctx.stroke();
ctx.closePath();
}
二、为了美观,实现书法类似的效果,需要设每个线段设置不同的宽度才可以
1)根据每两个事件点的时间差计算一个倍数关系,然后乘以一个基础宽度就可以得到不同的宽度,本文实现的效果是绘制越慢线条越宽,越快线条越窄

2) 设置线的连接方式和线端点效果,使整个线条看起来更加圆滑
/**
* 根据绘制时间差设置绘制线宽
**/
function getColor(coord) {
if (preCoord.length === 0) {
return;
}
// 当前是计算的每两个点的时间差是五毫秒的倍数
const tempMulti = (new Date().getTime() - preCoord[2]) / 5;
if (tempMulti > multi) {
multi = multi * 1.4;
} else {
multi = multi * 0.9;
}
if (multi > 5) {
multi = 5;
}
if (multi < 1) {
multi = 1;
}
ctx.lineWidth = 2 * multi; // 通过设置连线效果和线端点效果可以使线条看起来更圆滑
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.strokeStyle = 'rgba(153, 153, 153, 1)';
}
三、下面奉上完整的代码和效果图

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>signature</title>
</head>
<body style="text-align: center;">
<div>
<button id="output" style="margin: 10px;">导出</button>
</div> <canvas id="canvas" width="800" height="800" style="width: 800px;height: 800px;border: 1px solid gray;"></canvas>
</body>
</html>
<script type="module">
window.onload = (() => {
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d'); // 上一个绘制点的坐标
let preCoord = [];
// 绘制启动标志
let downFlag = false;
// 初始线宽
let multi = 5; /**
* 按下鼠标启动绘制标记
**/
canvas.addEventListener('mousedown', e => {
preCoord = [e.offsetX, e.offsetY, new Date().getTime()];
downFlag = true;
}) /**
* 鼠标松开结束绘制
**/
canvas.addEventListener('mouseup', e => {
downFlag = false;
})
canvas.addEventListener('mouseout', () => {
downFlag = false;
}) /**
* 鼠标移动时绘制文字
**/
canvas.addEventListener('mousemove', e => {
if (downFlag) {
const coord = [e.offsetX, e.offsetY];
drawSign(coord);
preCoord = [...coord, new Date().getTime()];
}
}) document.getElementById('output').addEventListener('click', e => {
const a = document.createElement('a');
a.href = canvas.toDataURL('image/png');
a.download = 'signature.png';
a.click();
}) /**
* 根据绘制时间差设置绘制线宽
**/
function getColor(coord) {
if (preCoord.length === 0) {
return;
}
// 当前是计算的每两个点的时间差是五毫秒的倍数
const tempMulti = (new Date().getTime() - preCoord[2]) / 5;
if (tempMulti > multi) {
multi = multi * 1.4;
} else {
multi = multi * 0.9;
}
if (multi > 5) {
multi = 5;
}
if (multi < 1) {
multi = 1;
}
ctx.lineWidth = 2 * multi; // 通过设置连线效果和线端点效果可以使线条看起来更圆滑
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.strokeStyle = 'rgba(153, 153, 153, 1)';
} function drawSign(coord) {
// 为了实现阶段性线的不同粗细程度,所以每次绘制必须重新开始一段路径
ctx.beginPath();
getColor(coord); ctx.lineTo(...preCoord);
ctx.lineTo(...coord); ctx.stroke();
ctx.closePath();
}
})
</script>
完整代码

如何通过canvas实现电子签名的更多相关文章
- Canvas电子签名和游戏化
今天一天的时间都在做包团报价的无流程原型设计,一方面参考了其他系统,一方面整理先在系统中不合理的部分,规范了报价元素的分类.梳理了意向需求,其实原来粗略的放了一个模板进去是听不靠谱的.客户的要求-&g ...
- 做移动端电子签名发现canvas的 一些坑
做移动端收集电子签名项目的时候发现了一些坑: 1. 移动端的手指按下.移动.抬起事件跟PC端的鼠标按下.移动.弹起事件是不一样的 2. canvas它的属性宽高和样式宽高是不一样的,通过CSS来设置c ...
- 表格技术七十二变|手把手教你用Canvas电子表格做电子签名
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 日常生活工作学习中,大家对电子表格必定不陌生.从工作数据汇总分析到出门收据各种电子发票,这些都是由电子表格制 ...
- 前端实现电子签名(web、移动端)通用组件(canvas实现)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- PHP《将画布(canvas)图像保存成本地图片的方法》
用PHP将网页上的Canvas图像保存到服务器上的方法 2014年6月27日 歪脖骇客 发表回复 8 在几年前HTML5还没有流行的时候,我们的项目经理曾经向我提出这样一个需求:让项目评审专家们在评审 ...
- JS框架_(Esign.js)仿信用卡电子签名特效
百度云盘 传送门 密码:l60w 电子签名特效效果: <!DOCTYPE html> <html> <head lang="en"> <m ...
- 迷你PS小程序-集成的开放式画报、油墨电子签名、图片拖拽可单独食用
米娜桑,哦哈哟~ 个人制作,该文章主要讲解最近基于uni-app框架编写的集图文拖拽等多方位编辑.油墨电子签名.开放式海报于一体的小程序的制作思路和实现代码. 目录 1.完整源码链接 2.实现思路 3 ...
- Jquery电子签名制作_jSignature
今天用Jquery的jSignature库制作一个电子签名 后台.net core上传到指定文件夹 下载jquery库 提取码:rd9g html @{ Layout = null; } <!D ...
- html5 canvas常用api总结(三)--图像变换API
canvas的图像变换api,可以帮助我们更加方便的绘画出一些酷炫的效果,也可以用来制作动画.接下来将总结一下canvas的变换方法,文末有一个例子来更加深刻的了解和利用这几个api. 1.画布旋转a ...
- 【探索】利用 canvas 实现数据压缩
前言 HTTP 支持 GZip 压缩,可节省不少传输资源.但遗憾的是,只有下载才有,上传并不支持.如果上传也能压缩,那就完美了.特别适合大量文本提交的场合,比如博客园,就是很好的例子. 虽然标准不支持 ...
随机推荐
- [CF1229E]Marek and Matching
This is a harder version of the problem. In this version, \(n \le 7\). Marek is working hard on crea ...
- 15、string
1.string是什么? Go中的字符串是一个字节的切片,可以通过将其内容封装起在""中来创建字符串.Go中的的字符串是Unicode兼容的并且是UTF-8编码的. 2.strin ...
- MybatisPlus高级特性之SimpleQuery工具类
1.是很么? SimpleQuery可以对selectList查询后的结果使用Stream流进行操作,使其可以返回指定的结果,简洁了api的调用 2.怎么玩? 案例演示 (1) list操作 /** ...
- 使用Py2neo更新Neo4j中节点的属性值的正确姿势
1 def findNode(name, graph): 2 matcher = NodeMatcher(graph) 3 m = matcher.match(name = name).first() ...
- 创建定义store并使用组合式api、选项式api
在项目根目录创建store文件夹(此步骤和vuex相同) 在步骤一的store文件夹下根据不同的用途场景创建单独的store文件(等同于vuex中分模块). 定义store基本步骤 步骤 导入defi ...
- 基于QT环境下,实现客户端红外采集人体向服务端通信。
一.本次测试目的 基于QT环境下STM32人体红外检测,实现客户端红外采集到信息向服务端通信. 二.功能 (1).传入音乐,当服务端接收到信息时,打开音乐 (2).在服务端上面显示图片,当接收到 ...
- JAVAAPI实现血缘关系Rest推送到DataHub V0.12.1版本
DataHub 更青睐于PythonAPI对血缘与元数据操作 虽然开源源码都有Java示例和Python示例:但是这个API示例数量简直是1:100的差距!!不知为何,项目使用Java编写,示例推送偏 ...
- 前端布局flex从入门到入土
前端布局flex从入门到入土 作为一个后端,谈不上多会前端,但是一些常见的布局都可以做到,例如flex布局.推荐菜鸟教程的布局:https://www.runoob.com/w3cnote/flex- ...
- SQL 的递归查询
在一般的业务场景中,特别是针对相关的业务线相关的功能开发时,可能会遇到一些具有层级关系的数据关联结构.比如,一个员工可能属于一个领导管辖,而同时,这个领导也被另一个更高级别的领导管辖--,而本质上这些 ...
- ubuntu中vim乱码以及执行shell脚本时出现乱码
vim打开文件中文出现乱码情况,可以参考如下办法: 在vim /usr/share/vim/vimrc文件末尾中加入 (这个vimrc文件是Vim 的系统级配置文件.文档.插件.语法高亮定义.颜色方案 ...