web前端 原生js签名板(电子签名)写字板 canvas 截图

article/2025/7/2 1:58:09

移动端在开发的时候,可能会涉及到手写签名(电子签名)那些,在前端的思路是使用canvas 来签名,导出成图片进行保存。

仅供参考和学习。

vue版本: https://blog.csdn.net/qq_33270001/article/details/102855964

注意:在移动端使用的时候, 写竖的时候, 页面会被往下拉, 手写板动了, 写字不顺畅. 建议在移动端的touchmove事件里, 加一行防止页的滑动事件, 代码是: event.preventDefault()

<!DOCTYPE html>
<!-- saved from url=(0056)http://hao2013.cn/canvas-special-master/brush/index.html -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>签名板(支持移动端)</title>
</head>
<style type="text/css">
*{margin: 0;padding: 0;}
.canvas {
/*width: 100%;*/
display: block;
border: 1px solid red;
}
#clear,
#clear1,
#save {
margin: 0 auto;
display: inline-block;
padding: 5px 10px;
width: 50px;
height: 40px;
line-height: 40px;
border: 1px solid #eee;
background: #e1e1e1;
border-radius: 10px;
text-align: center;
margin: 20px auto;
cursor: pointer;
}
</style>
<body data-ext-version="1.4.2">
<canvas id="canvas" width="600" height="600">您的浏览器不支持canvas技术,请升级浏览器!</canvas>
<div style="text-align: center">
<span id="clear">清空</span>
<span id="save">保存</span>
</div>
</body>
<script type="text/javascript">
function WriteFont(id, options) {
var self = this;
this.canvas = document.getElementById(id);
var obj = {
canvas: this.canvas,
context: this.canvas.getContext("2d"),
isWrite: false, //是否开始
lastWriteTime: -1,
lastWriteSpeed: 0,
lastWriteWidth: 0,
canvasWidth: 600, //canvas宽高
canvasHeight: 600,
isShowBorder: true, //是否显示网格
bgColor: '#fff', //背景色
borderWidth: 2, // 网格线宽度
borderColor: "#fff", //网格颜色
lastPoint: {}, //
writeWidth: 2, //基础轨迹宽度
maxWriteWidth: 30, // 写字模式最大线宽
minWriteWidth: 1, // 写字模式最小线宽
writeColor: '#000', // 轨迹颜色
isWriteName:false //签名模式
}for(var name in options) {
obj[name] = options[name];
}/**
* 轨迹宽度
*/
this.setLineWidth = function() {
var nowTime = new Date().getTime();
var diffTime = nowTime - obj.lastWriteTime;
obj.lastWriteTime = nowTime;
var returnNum = obj.minWriteWidth + (obj.maxWriteWidth - obj.minWriteWidth) * diffTime / 30;
if(returnNum < obj.minWriteWidth) {
returnNum = obj.minWriteWidth;
} else if(returnNum > obj.maxWriteWidth) {
returnNum = obj.maxWriteWidth;
}returnNum = returnNum.toFixed(2);
//写字模式和签名模式
if(obj.isWriteName){
obj.context.lineWidth = obj.writeWidth;
}else{
obj.context.lineWidth = obj.lastWriteWidth = obj.lastWriteWidth / 4 * 3 + returnNum / 4;
}
}/**
* 绘制轨迹
*/
this.writing = function(point) {
obj.context.beginPath();
obj.context.moveTo(obj.lastPoint.x, obj.lastPoint.y);
obj.context.lineTo(point.x, point.y);
self.setLineWidth();
obj.context.stroke();
obj.lastPoint = point;
obj.context.closePath();
}/**
* 轨迹样式
*/
this.writeContextStyle = function() {
obj.context.beginPath();
obj.context.strokeStyle = obj.writeColor;
obj.context.lineCap = 'round';
obj.context.lineJoin = "round";
}/**
* 写开始
*/
this.writeBegin = function(point) {
obj.isWrite = true;
obj.lastWriteTime = new Date().getTime();
obj.lastPoint = point;
self.writeContextStyle();
}/**
* 写结束
*/
this.writeEnd = function() {
obj.isWrite = false;
}/**
* 清空画板
*/
this.canvasClear = function() {
obj.context.save();
obj.context.strokeStyle = '#fff';
obj.context.clearRect(0, 0, obj.canvasWidth, obj.canvasHeight);
if(obj.isShowBorder && !obj.isWriteName) {
obj.context.beginPath();
var size = obj.borderWidth / 2;
//画外面的框
obj.context.moveTo(size, size);
obj.context.lineTo(obj.canvasWidth - size, size);
obj.context.lineTo(obj.canvasWidth - size, obj.canvasHeight - size);
obj.context.lineTo(size, obj.canvasHeight - size);
obj.context.closePath();
obj.context.lineWidth = obj.borderWidth;
obj.context.strokeStyle = obj.borderColor;
obj.context.stroke();
//画里面的框
obj.context.moveTo(0, 0);
obj.context.lineTo(obj.canvasWidth, obj.canvasHeight);
obj.context.lineTo(obj.canvasWidth, obj.canvasHeight / 2);
obj.context.lineTo(obj.canvasWidth, obj.canvasHeight / 2);
obj.context.lineTo(0, obj.canvasHeight / 2);
obj.context.lineTo(0, obj.canvasHeight);
obj.context.lineTo(obj.canvasWidth, 0);
obj.context.lineTo(obj.canvasWidth / 2, 0);
obj.context.lineTo(obj.canvasWidth / 2, obj.canvasHeight);
obj.context.stroke();}
obj.context.restore();
}/**
* 保存图片 格式base64
*/
this.saveAsImg = function() {
var image = new Image();
image.src = this.canvas.toDataURL("image/png");
if(image.src == this.emptyCanvas) {
alert('请先书写')
} else {
console.log('提交的内容===>', image.src)
}
};/**
* 初始化画板
*/
this.canvasInit = function() {
this.canvas.width = obj.canvasWidth;
this.canvas.height = obj.canvasHeight;
this.emptyCanvas = this.canvas.toDataURL("image/png");
}/**======================事件绑定===========================**/this.canvas.addEventListener('mousedown', function(e) {
var point = {
x: e.offsetX || e.clientX,
y: e.offsetY || e.clientY
};
self.writeBegin(point);
});this.canvas.addEventListener('mouseup', function(e) {
var point = {
x: e.offsetX,
y: e.offsetY
};
self.writeEnd(point);
});this.canvas.addEventListener('mouseleave', function(e) {
var point = {
x: e.offsetX,
y: e.offsetY
};
self.writeEnd(point);
});this.canvas.addEventListener('mousemove', function(e) {
if(obj.isWrite) {
var point = {
x: e.offsetX,
y: e.offsetY
};self.writing(point);
}
});//移动端
this.canvas.addEventListener('touchstart', function(e) {
var touch = e.targetTouches[0];
var point = {
x: touch.pageX || touch.clientX,
y: touch.pageY || touch.clientY
};
self.writeBegin(point);
});
this.canvas.addEventListener('touchend', function(e) {
var touch = e.changedTouches[0];
var point = {
x: touch.pageX,
y: touch.pageY
};
self.writeEnd(point);
});
this.canvas.addEventListener('touchmove', function(e) {
var touch = e.targetTouches[0];
var point = {
x: touch.pageX,
y: touch.pageY
};
self.writeEnd(point);
});
this.canvas.addEventListener('touchmove', function(e) {
var touch = e.targetTouches[0];
var point = {
x: touch.pageX,
y: touch.pageY
};
self.writing(point);
});this.canvasInit();
this.canvasClear();this.option = obj;
obj.control = {
clearCanvas: self.canvasClear
};
}/**
* 初始化调用
* 设置参数
*/
var writeCanvas = new WriteFont('canvas', {
borderWidth: 10,
writeWidth:3,
borderColor: '#ff6666',
isWriteName:true //签名模式
});document.getElementById('clear').onclick = function() {
writeCanvas.option.control.clearCanvas();
};document.getElementById('save').onclick = function() {
writeCanvas.saveAsImg()
};
</script>
</html>

效果图如下:

保存的时候是 base 64的图片

~VWA07XK)W$Y9O)[YH1{K@B.png

附上demo和源码

附件地址: http://hao2013.cn/zb_users/upload/2018/07/201807291807177677029.zip

参考:http://hao2013.cn/?id=41 


http://chatgpt.dhexx.cn/article/TSTH1vCO.shtml

相关文章

手写板签字php,手写板,签字版

1.建一个view .h文件复制以下代码 /** * 画布 */ interface SKGraphicView : UIView { CGPoint _start; CGPoint _move; CGMutablePathRef _path; NSMutableArray *_pathArray; CGFloat _lineWidth; UIColor *_color; } property (nonatomic,assign)CGFloat lineWidth;/**<…

前端手写电子签名板实现方案

前端手写电子签名板实现 作者&#xff1a; 很菜的小白在分享 时间&#xff1a;2022年12月29日 介绍 什么是电子签名 电子签名是指数据电文中以电子形式所含、所附用于识别签名人身份并表明签名人认可其中内容的数据。—— 百度百科 通俗点说其实就是通过在电子设备上进行类似纸…

sign-canvas 一个基于canvas开发,封装于Vue组件的通用手写签名板(电子签名板),支持pc端和移动端;

写在前面 : 在项目的开发过程中可能会涉及到手写签名(电子签名)那些&#xff0c;在前端的思路是使用canvas 来签名&#xff0c;导出成图片进行保存。 此轮子是继 https://blog.csdn.net/qq_33270001/article/details/81809535之后,用于vue项目中,为了方便自己与众人和复用而开…

无纸化手写电子签名是现今不可或缺的技术

说到手写电子签名&#xff0c;相信不少人都有所耳闻。在21世纪的今天&#xff0c;移动信息时代&#xff0c;在国家政策指引与倡导下&#xff0c;“无纸化”已成为一种趋势&#xff0c;手写电子签名技术正快速在各行各业推行&#xff0c;不仅节约了纸张资源&#xff0c;助力环境…

VB.net调用蒙恬Write2Go笔迹手写板进行电子签名

最近的项目需要用到手写电子签名的功能,挑来挑去最后选择了蒙恬Write2Go这款手写板设备,因为手写板上面直接就有一块电子油墨显示屏,所写即所得,还可以看到写的笔迹 安装完蒙恬的驱动及自带应用程序之后,经过测试发现,其工作原理是利用了windows剪切板作为中间桥梁来交换图片数…

uni-app - 电子签字板组件(签名专用写字画板,支持调整写字板 “横纵“ 方向,可调整线条粗细颜色等,Canvas 绘制非常丝滑流畅)完美兼容 H5 APP 小程序,最好用的画板签字教程插件源码

前言 网上的教程代码非常乱且都有 BUG 存在,非常难移植到自己的项目中,本文代码干净整洁注释详细。 本文实现了 全端兼容,签名专用的写字板组件,真机流畅丝滑且无 BUG, 您直接复制组件源码,按照详细示例+超详细的注释轻松几分钟完成, 如下图 真机测试,您还可以通过组件…

H5手写板电子签名开发

如图所示:前端实现H5canvas手写板电子签名:<!DOCTYPE html> <html lang"en"><head><meta charset"utf-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0, maximum-scale1.0, user-scala…

uniapp - 实现微信小程序电子签名板,横屏手写姓名签名专用写字画板(详细运行示例,一键复制开箱即用)

效果图 实现了在uniapp项目中,微信小程序平台流畅的写字签名板(也可以绘图)功能源码,复制粘贴,改改样式几分钟即可搞定! 支持自动横屏、持预览,真机运行测试非常流畅不卡顿。 基础模板 如下代码所示。 <template><view class=

Vue Canvas 实现电子签名 手写板

直接上代码 <template><section class"signature"><div class"signatureBox"><div class"canvasBox" ref"canvasHW"><canvas ref"canvasF" touchstarttouchStart touchmovetouchMove touchendt…

锁---一些锁学习

1、java锁之公平锁和非公平锁 公平锁 是指多个线程按照申请的顺序来获取&#xff0c;类似排队打饭&#xff0c;先来后到。 非公平锁 是指多个线程获取锁的顺序并不是按照申请锁的顺序&#xff0c;有可能后申请的线程比先申请的线程优先获取锁&#xff0c;在高并发的情况下&a…

C# 实现锁屏

首先&#xff0c;将窗体的FormBorderStyle设置为none&#xff0c;WindowState设为Maximized 让窗体占据整个页面。 form窗体代码&#xff1a; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using …

win11中睡眠唤醒后如何禁止锁屏界面及登录界面

第一步禁止锁屏界面 gpedit.msc 不显示锁屏-》已启用 第二步&#xff1a;不显示登陆框 netplwiz 经过以上设置以后&#xff0c;打开笔记本就可以直接显示桌面了。

办公计算机锁屏方法,电脑快速锁屏,办公室神技能,再也不怕别人看我的电脑了!...

原标题&#xff1a;电脑快速锁屏&#xff0c;办公室神技能&#xff0c;再也不怕别人看我的电脑了&#xff01; 现在快节奏的社会&#xff0c;电脑的更方面性能与功能是非常之大&#xff0c;我们对电脑的使用频率也越来越高&#xff0c;可见它对我们生活越来越重要。在我们平时使…

Android锁屏的解锁(九个点),使用画的方式,大致的步骤

这篇博客是全部代码(没有解释,纯代码): https://blog.csdn.net/weixin_44614751/article/details/103101104 效果: 第一步:添加背景 第二步:创建九个点 先读取每一个点的图片: creatDot 创建九个点: initNin

ubuntu 18.04取消自动锁屏功能

有时候几分钟不用Ubuntu&#xff0c;系统就自动锁屏了&#xff0c;这是一种安全措施&#xff0c;防止别人趁你不在时使用你的系统。但对于大部分人而言&#xff0c;这是没有必要的&#xff0c;尤其是Ubuntu虚拟机&#xff0c;里面没啥重要的东西&#xff0c;每次锁屏后需要重新…

Android 通知栏,锁屏播放音乐,类似音乐播放器

项目中需要用到播放音频的功能&#xff0c;想做一个类似酷狗、酷我这样的音频播放功能&#xff0c;在通知栏和锁屏时都可以操控音乐&#xff0c;开发中发现oppo reno手机在锁屏时不显示通知栏&#xff0c;研究了整整一天终于解决&#xff0c;特作记录&#xff0c;给遇到同样问题…

Android自定义锁屏实现----仿正点闹钟滑屏解锁

本文原创&#xff0c;转载请注明出处&#xff1a;http://blog.csdn.net/qinjuning 前几周看了下解锁的框架&#xff0c;基本上算是弄了个脸熟。看着别人花哨的解锁界面&#xff0c;心里也很痒痒的。于是&#xff0c;画了一天时间&#xff0c; 捣鼓出了这个成果----仿正点闹钟解…

易安卓打开Android系统中的解锁方式选择页面(锁屏方式选择)

感谢名单 感谢fylfyl2写的https://blog.csdn.net/fyilun/article/details/21257595 E4A打开锁屏方式页面 Intent intent new Intent(); ComponentName cm new ComponentName("com.android.settings","com.android.settings.ChooseLockGeneric"); inte…

Android锁屏的解锁(九个点),使用画的方式

一、效果展示: 这篇博客有解释大概的步骤: https://blog.csdn.net/weixin_44614751/article/details/103101199 二、代码部分: MainActivity.java中的代码: package com.example.drawunlock1;import androidx.appcompat.app.AppCompatActivity;import android.content.re…

让电脑不被锁屏的方法,亲测有效

通过JS来控制键盘&#xff0c;定时按下SCROLLLOCK键&#xff0c;达到电脑不会被锁屏的效果。 通常公司电脑都会自动锁屏&#xff0c;只是时间有长短。有时候闲着了不用电脑&#xff0c;但是却不想让电脑锁屏。那么可以用js代码来控制键盘的按键循环按下实现不锁屏的效果&#x…