如何通过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 压缩,可节省不少传输资源.但遗憾的是,只有下载才有,上传并不支持.如果上传也能压缩,那就完美了.特别适合大量文本提交的场合,比如博客园,就是很好的例子. 虽然标准不支持 ...
随机推荐
- [AGC003D] Anticube
Problem Statement Snuke got positive integers $s_1,...,s_N$ from his mother, as a birthday present. ...
- 接收json数据
1.导入坐标: <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId& ...
- 【UniApp】-uni-app-处理项目输入数据(苹果计算器)
前言 上一篇文章完成了项目的基本布局,这一篇文章我们来处理一下项目的输入数据 项目的输入数据主要是通过按键来输入的,所以我们需要对按键进行处理 那么我们就来看一下 uni-app-处理项目输入数据 步 ...
- 文心一言大模型-function Calling的应用
"大模型的函数调用"(Large Model Function Calling)是一个涉及到在大型人工智能模型,如 GPT-4 或类似的高级深度学习模型中使用函数调用的概念.在这种 ...
- Ubuntu系统部署后优化
Ubuntu系统配置调整 前期准备 #更改主机名,重启后不变 hostnamectl set-hostname Zabbix-Server01 #更改主机名,重启后变回从前 hostname Zabb ...
- 神经网络优化篇:梯度检验应用的注意事项(Gradient Checking Implementation Notes)
梯度检验应用的注意事项 分享一些关于如何在神经网络实施梯度检验的实用技巧和注意事项. 首先,不要在训练中使用梯度检验,它只用于调试.意思是,计算所有\(i\)值的\(d\theta_{\text{ap ...
- vue3 + element-plus 的 upload + axios + django 文件上传并保存
之前在网上搜了好多教程,一直没有找到合适自己的,要么只有前端部分没有后端,要么就是写的不是很明白.所以还得靠自己摸索出来后,来此记录一下整个过程. 其实就是不要用默认的 action,要手动实现上传方 ...
- Spring Boot入坑-2-第一个Spring Boot项目
Spring Boot简介 自从2014年4月Pivotal团队推出以来,作为一个基于Spring的开源轻量级框架,备受企业级应用喜爱 简化Spring应用的搭建与开发过程 是对Spring缺点进行的 ...
- 《架构整洁之道》学习笔记 Part 1 概述
本书主题 介绍什么是优秀的软件架构,以提高软件架构质量 介绍系统架构的各种属性与成本和生产力的关系,以采用好的设计和架构以便减少构建成本 好的软件架构可以带来什么? 大大节省软件项目构建与维护的人力成 ...
- Programming Abstractions in C阅读笔记:p246-p247
<Programming Abstractions in C>学习第68天,p246-p247总结,总计2页. 一.技术总结 本章通过"the game of nim(尼姆游戏) ...