HTML5 Canvas 实现在线签字功能(示例代码)

2025-12-13 0 821

前言

在现代互联网应用中,有时我们需要让用户网页上进行签字操作,比如确认文件、填写电子表格或者签署合同。利用 HTML5 的 canvas 画布,我们可以轻松地实现这一功能,为用户提供方便快捷的在线签字体验。

一、HTML5 Canvas 简介

HTML5 的 canvas 元素是一种强大的图形渲染工具,它允许开发者使用 JavaScript 在网页上绘制各种图形、动画和交互式内容。通过 canvas,开发者可以创建丰富多彩的视觉效果,并实现复杂的用户交互体验。

HTML5 Canvas的关键特性:

图形绘制能力:Canvas 元素提供了绘制路径、矩形、圆形、直线、文本等基本图形的功能,同时还支持图像的绘制和变换操作,使得开发者能够轻松地创建各种视觉效果。

动画和交互:借助 JavaScript,开发者可以在 Canvas 上创建复杂的动画效果,并添加交互式的操作。这使得 Canvas 成为开发游戏、数据可视化和其他需要动态效果的应用的理想选择。

性能优势:由于 Canvas 是基于 GPU 加速的,因此它具有良好的性能表现,能够处理大量的图形元素和动画效果,而不会对页面的整体性能产生太大影响。

灵活性:Canvas 元素可以轻松地与其他 HTML 元素结合使用,使得开发者可以在页面上创建复杂的混合媒体效果,同时还可以响应用户的交互操作。

二、签字功能的实现

效果演示

HTML5 Canvas 实现在线签字功能(示例代码)

完整代码

HTML代码

<!DOCTYPE html>
<htmlclass=\”no-js\”>
<head>
<metaname=\”viewport\”
content=\”width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0,user-scalable=no,viewport-fit=cover\”>
<metahttp-equiv=\”Cache-Control\”content=\”no-cache, no-store, must-revalidate\”/>
<metahttp-equiv=\”expires\”CONTENT=\”Wed, 26 Feb 1997 08:21:57 GMT\”>
<metahttp-equiv=\”Content-Type\”content=\”text/html; charset=UTF-8\”>
<metahttp-equiv=\”X-UA-Compatible\”content=\”IE=edge\”>
<metahttp-equiv=\”Pragma\”content=\”no-cache\”>
<metahttp-equiv=\”Cache\”content=\”no-cache\”>
<metahttp-equiv=\”Expires\”content=\”0\”>
<metacharset=\”utf-8\”>
<title>画图</title>
<linkrel=\”stylesheet\”href=\”css/bootstrap.css\”>
<style>
* {
margin: 0;
padding: 0;
}
html,
body {
width: 100%;
height: 100%;
text-align: center;
}
canvas {
max-width: 100%;
border: 2px dotted #ccc;
}
</style>
</head>
<body>
<scriptsrc=\”./index.js\”></script>
<script>
//初始化
var sign = new Draw( {
// canvas:document.getElementById(\’canvas\’),
lineWidth: 10, // 线条宽度
width: 400, // canvas 宽
height: 400, //canvas 高
strokeStyle: \’#333333\’ // 线条颜色
} );
window.onload = function () {
// 点击输出图片
document.querySelector( \’.ouput\’ ).onclick = function () {
var img = new Image();
img.style.width = \’200px\’;
img.src = sign.ouput();
img.onload = function () {
document.body.appendChild( img );
}
document.querySelector( \’img\’ ) && document.querySelector( \’img\’ ).remove();
}
// 点击清除
document.querySelector( \’.clear\’ ).onclick = function () {
sign.clear();
}
// 点击撤销
document.querySelector( \’.undo\’ ).onclick = function () {
if ( sign.state.undopath.length > 0 ) {
sign.undo();
} else {
console.log( \’还没有签名\’ );
}
}
}
</script>
<divclass=\”buttons\”>
<buttontype=\”button\”class=\”btn btn-primary ouput\”>生成图片</button>
<buttontype=\”button\”class=\”btn btn-light undo\”>撤销</button>
<buttontype=\”button\”class=\”btn btn-light clear\”>清除画布</button>
</div>
</body>
</html>

js代码

(function( global, factory ) {
typeofexports ===\’object\’&&typeofmodule !==\’undefined\’? module.exports = factory() :
typeofdefine ===\’function\’&& define.amd ? define( factory ) :
( global = global || self, global.Draw = factory() );
}(this, (function() {
\’use strict\’;
varclassCallCheck =function( instance, Constructor ) {
if( !( instanceinstanceofConstructor ) ) {
thrownewTypeError(\”Cannot call a class as a function\”);
}
};
varcreateClass =function() {
functiondefineProperties ( target, props ) {
for(vari = 0; i < props.length; i++ ) {
vardescriptor = props[i];
descriptor.enumerable = descriptor.enumerable ||false;
descriptor.configurable =true;
if(\”value\”indescriptor ) descriptor.writable =true;
Object.defineProperty( target, descriptor.key, descriptor );
}
}
returnfunction( Constructor, protoProps, staticProps ) {
if( protoProps ) defineProperties( Constructor.prototype, protoProps );
if( staticProps ) defineProperties( Constructor, staticProps );
returnConstructor;
};
}();
/**
*
* @description 手写签字版
*/
varDraw =function() {
functionDraw () {
varparams = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
classCallCheck(this, Draw );
this.el = params.el || document.createElement(\’canvas\’);
this.state = {
undopath: [],
index: -1,
old: void 0,
isStart:false,
width: params.width || 400,
height: params.height || 400,
lineWidth: params.lineWidth || 1,
isTouch:\’ontouchstart\’inwindow,
strokeStyle: params.strokeStyle ||\’#333333\’
};
var_state =this.state,
width = _state.width,
height = _state.height,
lineWidth = _state.lineWidth;
this.el.width = width * 2;
this.el.height = height * 2;
document.body.appendChild(this.el );
this.ctx =this.el.getContext(\’2d\’);
this.ctx.scale( 2, 2 );
this.ctx.lineWidth = lineWidth;
this.ctx.lineJoin =\’round\’;
this.ctx.lineCap =\’round\’;
this.init();
}
createClass( Draw, [{
key:\’onStart\’,
value:functiononStart () {
++this.state.index;
this.state.isStart =true;
}
}, {
key:\’onMove\’,
value:functiononMove ( e ) {
e.preventDefault();
if( !this.state.isStart )return;
varpos =this.pos( e );
varindex =this.state.index;
this.ctx.strokeStyle =this.state.strokeStyle;
if(this.state.old ) {
this.ctx.beginPath();
this.ctx.moveTo(this.state.old.x,this.state.old.y );
this.ctx.lineTo( pos.x, pos.y );
this.ctx.stroke();
}
this.state.old = pos;
if(this.state.undopath[index] ) {
this.state.undopath[index].push( { x:this.state.old.x, y:this.state.old.y } );
}else{
this.state.undopath[index] = [{
x:this.state.old.x,
y:this.state.old.y,
strokeStyle:this.ctx.strokeStyle,
lineWidth:this.ctx.lineWidth
}];
}
}
}, {
key:\’onEnd\’,
value:functiononEnd () {
this.state.old = void 0;
this.state.isStart =false;
}
}, {
key:\’pos\’,
value:functionpos ( e ) {
varx = 0,
y = 0;
if( e.touches ) {
x = e.touches[0].pageX;
y = e.touches[0].pageY;
}else{
x = e.offsetX / 2;
y = e.offsetY / 2;
}
return{ x: x, y: y };
}
}, {
key:\’ouput\’,
value:functionouput () {
// 输出图片
returnthis.el.toDataURL();
}
}, {
key:\’init\’,
value:functioninit () {
// 绑定事件
varisTouch =this.state.isTouch;
this.el.addEventListener( isTouch ?\’touchstart\’:\’mousedown\’,this.onStart.bind(this),false);
this.el.addEventListener( isTouch ?\’touchmove\’:\’mousemove\’,this.onMove.bind(this),false);
this.el.addEventListener( isTouch ?\’touchend\’:\’mouseup\’,this.onEnd.bind(this),false);
this.el.addEventListener( isTouch ?\’touchcancel\’:\’mouseout\’,this.onEnd.bind(this),false);
}
}, {
key:\’destroyed\’,
value:functiondestroyed () {
if(this.el ) {
varisTouch =this.state.isTouch;
this.el.removeEventListener( isTouch ?\’touchstart\’:\’mousedown\’,this.onStart.bind(this) );
this.el.removeEventListener( isTouch ?\’touchmove\’:\’mousemove\’,this.onMove.bind(this) );
this.el.removeEventListener( isTouch ?\’touchend\’:\’mouseup\’,this.onEnd.bind(this) );
this.el.removeEventListener( isTouch ?\’touchcancel\’:\’mouseout\’,this.onEnd.bind(this) );
}
}
}, {
key:\’clear\’,
value:functionclear () {
// 清除画布
this.state.index = -1;
this.state.undopath = [];
this.ctx.clearRect( 0, 0,this.el.width,this.el.height );
}
}, {
key:\’undo\’,
value:functionundo () {
// 撤销
this.state.index >= 0 && –this.state.index;
varundopath =this.state.undopath;
this.state.undopath.pop();
this.ctx.clearRect( 0, 0,this.el.width,this.el.height );
if( undopath ) {
this.ctx.beginPath();
for(varz = 0; z < undopath.length; ++z ) {
this.ctx.moveTo( undopath[z][0].x, undopath[z][0].y );
this.ctx.lineWidth = undopath[z][0].lineWidth;
this.ctx.strokeStyle = undopath[z][0].strokeStyle;
for(vari = 0; i < undopath[z].length; ++i ) {
this.ctx.lineTo( undopath[z][i].x, undopath[z][i].y );
}
}
this.ctx.stroke();
this.ctx.closePath();
}else{
this.state.undopath = [];
}
}
}] );
returnDraw;
}();
returnDraw;
} ) ) );

到此这篇关于HTML5 Canvas 实现在线签字功能的文章就介绍到这了,更多相关HTML5 Canvas在线签字内容请搜索脚本之家以前的文章或继续浏览下面的相关文章,希望大家以后多多支持脚本之家!

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

左子网 编程相关 HTML5 Canvas 实现在线签字功能(示例代码) https://www.zuozi.net/36673.html

常见问题
  • 1、自动:拍下后,点击(下载)链接即可下载;2、手动:拍下后,联系卖家发放即可或者联系官方找开发者发货。
查看详情
  • 1、源码默认交易周期:手动发货商品为1-3天,并且用户付款金额将会进入平台担保直到交易完成或者3-7天即可发放,如遇纠纷无限期延长收款金额直至纠纷解决或者退款!;
查看详情
  • 1、描述:源码描述(含标题)与实际源码不一致的(例:货不对板); 2、演示:有演示站时,与实际源码小于95%一致的(但描述中有”不保证完全一样、有变化的可能性”类似显著声明的除外); 3、发货:不发货可无理由退款; 4、安装:免费提供安装服务的源码但卖家不履行的; 5、收费:价格虚标,额外收取其他费用的(但描述中有显著声明或双方交易前有商定的除外); 6、其他:如质量方面的硬性常规问题BUG等。 注:经核实符合上述任一,均支持退款,但卖家予以积极解决问题则除外。
查看详情
  • 1、左子会对双方交易的过程及交易商品的快照进行永久存档,以确保交易的真实、有效、安全! 2、左子无法对如“永久包更新”、“永久技术支持”等类似交易之后的商家承诺做担保,请买家自行鉴别; 3、在源码同时有网站演示与图片演示,且站演与图演不一致时,默认按图演作为纠纷评判依据(特别声明或有商定除外); 4、在没有”无任何正当退款依据”的前提下,商品写有”一旦售出,概不支持退款”等类似的声明,视为无效声明; 5、在未拍下前,双方在QQ上所商定的交易内容,亦可成为纠纷评判依据(商定与描述冲突时,商定为准); 6、因聊天记录可作为纠纷评判依据,故双方联系时,只与对方在左子上所留的QQ、手机号沟通,以防对方不承认自我承诺。 7、虽然交易产生纠纷的几率很小,但一定要保留如聊天记录、手机短信等这样的重要信息,以防产生纠纷时便于左子介入快速处理。
查看详情

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务