想要实现一个电子签名,可以支持鼠标签名,还能类似书法效果线条有粗有细,同时可以导出成图片.

一、实现连贯的划线

  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实现电子签名的更多相关文章

  1. Canvas电子签名和游戏化

    今天一天的时间都在做包团报价的无流程原型设计,一方面参考了其他系统,一方面整理先在系统中不合理的部分,规范了报价元素的分类.梳理了意向需求,其实原来粗略的放了一个模板进去是听不靠谱的.客户的要求-&g ...

  2. 做移动端电子签名发现canvas的 一些坑

    做移动端收集电子签名项目的时候发现了一些坑: 1. 移动端的手指按下.移动.抬起事件跟PC端的鼠标按下.移动.弹起事件是不一样的 2. canvas它的属性宽高和样式宽高是不一样的,通过CSS来设置c ...

  3. 表格技术七十二变|手把手教你用Canvas电子表格做电子签名

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 日常生活工作学习中,大家对电子表格必定不陌生.从工作数据汇总分析到出门收据各种电子发票,这些都是由电子表格制 ...

  4. 前端实现电子签名(web、移动端)通用组件(canvas实现)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. PHP《将画布(canvas)图像保存成本地图片的方法》

    用PHP将网页上的Canvas图像保存到服务器上的方法 2014年6月27日 歪脖骇客 发表回复 8 在几年前HTML5还没有流行的时候,我们的项目经理曾经向我提出这样一个需求:让项目评审专家们在评审 ...

  6. JS框架_(Esign.js)仿信用卡电子签名特效

    百度云盘 传送门 密码:l60w 电子签名特效效果: <!DOCTYPE html> <html> <head lang="en"> <m ...

  7. 迷你PS小程序-集成的开放式画报、油墨电子签名、图片拖拽可单独食用

    米娜桑,哦哈哟~ 个人制作,该文章主要讲解最近基于uni-app框架编写的集图文拖拽等多方位编辑.油墨电子签名.开放式海报于一体的小程序的制作思路和实现代码. 目录 1.完整源码链接 2.实现思路 3 ...

  8. Jquery电子签名制作_jSignature

    今天用Jquery的jSignature库制作一个电子签名 后台.net core上传到指定文件夹 下载jquery库 提取码:rd9g html @{ Layout = null; } <!D ...

  9. html5 canvas常用api总结(三)--图像变换API

    canvas的图像变换api,可以帮助我们更加方便的绘画出一些酷炫的效果,也可以用来制作动画.接下来将总结一下canvas的变换方法,文末有一个例子来更加深刻的了解和利用这几个api. 1.画布旋转a ...

  10. 【探索】利用 canvas 实现数据压缩

    前言 HTTP 支持 GZip 压缩,可节省不少传输资源.但遗憾的是,只有下载才有,上传并不支持.如果上传也能压缩,那就完美了.特别适合大量文本提交的场合,比如博客园,就是很好的例子. 虽然标准不支持 ...

随机推荐

  1. System类的方法

    1.exit() 2.currentTimeMills() 代码练习

  2. 三个月我迁移了100PB数据

    2023年马上结束,这一年做了不少事情,有一项我可以吹好几年,忍不住和大家分享一下啊. 需求 去年底收到一项需求,要求2个月内从某云存储迁移100PB数据到微软云存储,包含几百亿个文件.当时听到这个数 ...

  3. Python——第五章:pickle模块

    序列化:把对象转化成二进制字节 反序列化:把二进制字节转化回对象 Pickle模块的常见用法: Pickle.dunps   把对象(数据)转化成字节 Pickle.loads   把字节转化回对象( ...

  4. 终于卷完了!MySQL 打怪升级进阶成神之路(2023 最新版)!

    从第一篇文章开始,我们逐步详细介绍了 MySQL 数据库的基础知识,如:数据类型.存储引擎.性能优化(软.硬及sql语句),MySQL 数据库的高可用架构的部分,如:主从同步.读写分离的原理与实践.跨 ...

  5. Pulsar3.0新功能介绍

    在上一篇文章 Pulsar3.0 升级指北讲了关于升级 Pulsar 集群的关键步骤与灾难恢复,本次主要分享一些 Pulsar3.0 的新功能与可能带来的一些问题. 升级后所遇到的问题 先来个欲扬先抑 ...

  6. Havoc插件编写

    ‍ 配置文件的webhook支持discord,所以尝试使用钉钉和企业微信. WebHook { Discord { Url = "" AvatarUrl = "&quo ...

  7. $router.push跳转页面传参

    $router.push传参与收参 //传参 <el-button type="text" @click="$router.push('/games/Match?i ...

  8. C++篇:第七章_结构体、共用体和枚举_知识点大全

    C++篇为本人学C++时所做笔记(特别是疑难杂点),全是硬货,虽然看着枯燥但会让你收益颇丰,可用作学习C++的一大利器 七.结构体.共用体和枚举 (一)结构体 C++的结构体中可以有构造函数,例: s ...

  9. 经典永流传,华为云媒体 AI 让老电影焕发新生

    摘要:近日,在华为云TechWave全球技术峰会(人工智能&数据)上,马栏山视频文创产业园首席专家周苏岳受邀发表演讲<经典永流传,媒体 AI 让老电影焕发新生>,分享与华为云原生媒 ...

  10. Error: Could not find or load main class org.elasticsearch.tools.java_version_checker.JavaVersionChecker

    把elasticsearch目录换到不属于root目录的其他目录就行了