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

ID:16229 / 打印

前言

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

一、HTML5 Canvas 简介

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

HTML5 Canvas的关键特性:

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

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

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

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

二、签字功能的实现

效果演示

完整代码

HTML代码

<!DOCTYPE html> <html class="no-js"> <head>     <meta name="viewport"         content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0,user-scalable=no,viewport-fit=cover">     <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />     <meta http-equiv="expires" CONTENT="Wed, 26 Feb 1997 08:21:57 GMT">     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">     <meta http-equiv="X-UA-Compatible" content="IE=edge">     <meta http-equiv="Pragma" content="no-cache">     <meta http-equiv="Cache" content="no-cache">     <meta http-equiv="Expires" content="0">     <meta charset="utf-8">     <title>画图</title>     <link rel="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>     <script src="./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>     <div class="buttons">         <button type="button" class="btn btn-primary ouput">生成图片</button>         <button type="button" class="btn btn-light undo">撤销</button>         <button type="button" class="btn btn-light clear">清除画布</button>     </div> </body> </html>

js代码

( function ( global, factory ) {     typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :         typeof define === 'function' && define.amd ? define( factory ) :             ( global = global || self, global.Draw = factory() ); }( this, ( function () {     'use strict';     var classCallCheck = function ( instance, Constructor ) {         if ( !( instance instanceof Constructor ) ) {             throw new TypeError( "Cannot call a class as a function" );         }     };     var createClass = function () {         function defineProperties ( target, props ) {             for ( var i = 0; i < props.length; i++ ) {                 var descriptor = props[i];                 descriptor.enumerable = descriptor.enumerable || false;                 descriptor.configurable = true;                 if ( "value" in descriptor ) descriptor.writable = true;                 Object.defineProperty( target, descriptor.key, descriptor );             }         }         return function ( Constructor, protoProps, staticProps ) {             if ( protoProps ) defineProperties( Constructor.prototype, protoProps );             if ( staticProps ) defineProperties( Constructor, staticProps );             return Constructor;         };     }();     /**      *       * @description  手写签字版      */     var Draw = function () {         function Draw () {             var params = 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' in window,                 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: function onStart () {                 ++this.state.index;                 this.state.isStart = true;             }         }, {             key: 'onMove',             value: function onMove ( e ) {                 e.preventDefault();                 if ( !this.state.isStart ) return;                 var pos = this.pos( e );                 var index = 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: function onEnd () {                 this.state.old = void 0;                 this.state.isStart = false;             }         }, {             key: 'pos',             value: function pos ( e ) {                 var x = 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: function ouput () {                 // 输出图片                 return this.el.toDataURL();             }         }, {             key: 'init',             value: function init () {                 // 绑定事件                 var isTouch = 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: function destroyed () {                 if ( this.el ) {                     var isTouch = 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: function clear () {                 // 清除画布                 this.state.index = -1;                 this.state.undopath = [];                 this.ctx.clearRect( 0, 0, this.el.width, this.el.height );             }         }, {             key: 'undo',             value: function undo () {                 // 撤销                 this.state.index >= 0 && --this.state.index;                 var undopath = this.state.undopath;                 this.state.undopath.pop();                 this.ctx.clearRect( 0, 0, this.el.width, this.el.height );                 if ( undopath ) {                     this.ctx.beginPath();                     for ( var z = 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 ( var i = 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 = [];                 }             }         }] );         return Draw;     }();     return Draw; } ) ) );
上一篇: HTML5使用<blockquote>标签实现段落缩进效果
下一篇: uniapp在h5页面实现扫码功能(html5-qrcode)

作者:admin @ 24资源网   2024-11-01

本站所有软件、源码、文章均有网友提供,如有侵权联系308410122@qq.com

与本文相关文章

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。