• 设为首页
  • 收藏本站
  • 积分充值
  • VIP赞助
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    福建二哥 门户 查看主题

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

    发布者: 404号房间 | 发布时间: 2025-6-14 15:09| 查看数: 116| 评论数: 0|帖子模式

    前言

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

    HTML5 的 canvas 元素是一种强大的图形渲染工具,它允许开发者使用 JavaScript 在网页上绘制各种图形、动画和交互式内容。通过 canvas,开发者可以创建丰富多彩的视觉效果,并实现复杂的用户交互体验。
    HTML5 Canvas的关键特性:
    1. <strong>图形绘制能力</strong>:Canvas 元素提供了绘制路径、矩形、圆形、直线、文本等基本图形的功能,同时还支持图像的绘制和变换操作,使得开发者能够轻松地创建各种视觉效果。
    2. <strong>动画和交互</strong>:借助 JavaScript,开发者可以在 Canvas 上创建复杂的动画效果,并添加交互式的操作。这使得 Canvas 成为开发游戏、数据可视化和其他需要动态效果的应用的理想选择。
    3. <strong>性能优势</strong>:由于 Canvas 是基于 GPU 加速的,因此它具有良好的性能表现,能够处理大量的图形元素和动画效果,而不会对页面的整体性能产生太大影响。
    4. <strong>灵活性</strong>:Canvas 元素可以轻松地与其他 HTML 元素结合使用,使得开发者可以在页面上创建复杂的混合媒体效果,同时还可以响应用户的交互操作。
    复制代码
    二、签字功能的实现

    效果演示

    完整代码
    HTML代码
    1. <!DOCTYPE html>
    2. <html class="no-js">
    3. <head>
    4.     <meta name="viewport"
    5.         content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0,user-scalable=no,viewport-fit=cover">
    6.     <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
    7.     <meta http-equiv="expires" CONTENT="Wed, 26 Feb 1997 08:21:57 GMT">
    8.     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    9.     <meta http-equiv="X-UA-Compatible" content="IE=edge">
    10.     <meta http-equiv="Pragma" content="no-cache">
    11.     <meta http-equiv="Cache" content="no-cache">
    12.     <meta http-equiv="Expires" content="0">
    13.     <meta charset="utf-8">
    14.     <title>画图</title>
    15.     <link rel="stylesheet" href="css/bootstrap.css">
    16.     <style>
    17.         * {
    18.             margin: 0;
    19.             padding: 0;
    20.         }
    21.         html,
    22.         body {
    23.             width: 100%;
    24.             height: 100%;
    25.             text-align: center;
    26.         }
    27.         canvas {
    28.             max-width: 100%;
    29.             border: 2px dotted #ccc;
    30.         }
    31.     </style>
    32. </head>
    33. <body>
    34.     <script src="./index.js"></script>
    35.     <script>
    36.         //初始化
    37.         var sign = new Draw( {
    38.             // canvas:document.getElementById('canvas'),
    39.             lineWidth: 10, // 线条宽度
    40.             width: 400, // canvas 宽
    41.             height: 400, //canvas 高
    42.             strokeStyle: '#333333' // 线条颜色
    43.         } );
    44.         window.onload = function () {
    45.             // 点击输出图片
    46.             document.querySelector( '.ouput' ).onclick = function () {
    47.                 var img = new Image();
    48.                 img.style.width = '200px';
    49.                 img.src = sign.ouput();
    50.                 img.onload = function () {
    51.                     document.body.appendChild( img );
    52.                 }
    53.                 document.querySelector( 'img' ) && document.querySelector( 'img' ).remove();
    54.             }
    55.             // 点击清除
    56.             document.querySelector( '.clear' ).onclick = function () {
    57.                 sign.clear();
    58.             }
    59.             // 点击撤销
    60.             document.querySelector( '.undo' ).onclick = function () {
    61.                 if ( sign.state.undopath.length > 0 ) {
    62.                     sign.undo();
    63.                 } else {
    64.                     console.log( '还没有签名' );
    65.                 }
    66.             }
    67.         }
    68.     </script>
    69.     <div class="buttons">
    70.         <button type="button" class="btn btn-primary ouput">生成图片</button>
    71.         <button type="button" class="btn btn-light undo">撤销</button>
    72.         <button type="button" class="btn btn-light clear">清除画布</button>
    73.     </div>
    74. </body>
    75. </html>
    复制代码
    js代码
    1. ( function ( global, factory ) {
    2.     typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
    3.         typeof define === 'function' && define.amd ? define( factory ) :
    4.             ( global = global || self, global.Draw = factory() );
    5. }( this, ( function () {
    6.     'use strict';
    7.     var classCallCheck = function ( instance, Constructor ) {
    8.         if ( !( instance instanceof Constructor ) ) {
    9.             throw new TypeError( "Cannot call a class as a function" );
    10.         }
    11.     };
    12.     var createClass = function () {
    13.         function defineProperties ( target, props ) {
    14.             for ( var i = 0; i < props.length; i++ ) {
    15.                 var descriptor = props[i];
    16.                 descriptor.enumerable = descriptor.enumerable || false;
    17.                 descriptor.configurable = true;
    18.                 if ( "value" in descriptor ) descriptor.writable = true;
    19.                 Object.defineProperty( target, descriptor.key, descriptor );
    20.             }
    21.         }
    22.         return function ( Constructor, protoProps, staticProps ) {
    23.             if ( protoProps ) defineProperties( Constructor.prototype, protoProps );
    24.             if ( staticProps ) defineProperties( Constructor, staticProps );
    25.             return Constructor;
    26.         };
    27.     }();
    28.     /**
    29.      *
    30.      * @description  手写签字版
    31.      */
    32.     var Draw = function () {
    33.         function Draw () {
    34.             var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
    35.             classCallCheck( this, Draw );
    36.             this.el = params.el || document.createElement( 'canvas' );
    37.             this.state = {
    38.                 undopath: [],
    39.                 index: -1,
    40.                 old: void 0,
    41.                 isStart: false,
    42.                 width: params.width || 400,
    43.                 height: params.height || 400,
    44.                 lineWidth: params.lineWidth || 1,
    45.                 isTouch: 'ontouchstart' in window,
    46.                 strokeStyle: params.strokeStyle || '#333333'
    47.             };
    48.             var _state = this.state,
    49.                 width = _state.width,
    50.                 height = _state.height,
    51.                 lineWidth = _state.lineWidth;
    52.             this.el.width = width * 2;
    53.             this.el.height = height * 2;
    54.             document.body.appendChild( this.el );
    55.             this.ctx = this.el.getContext( '2d' );
    56.             this.ctx.scale( 2, 2 );
    57.             this.ctx.lineWidth = lineWidth;
    58.             this.ctx.lineJoin = 'round';
    59.             this.ctx.lineCap = 'round';
    60.             this.init();
    61.         }
    62.         createClass( Draw, [{
    63.             key: 'onStart',
    64.             value: function onStart () {
    65.                 ++this.state.index;
    66.                 this.state.isStart = true;
    67.             }
    68.         }, {
    69.             key: 'onMove',
    70.             value: function onMove ( e ) {
    71.                 e.preventDefault();
    72.                 if ( !this.state.isStart ) return;
    73.                 var pos = this.pos( e );
    74.                 var index = this.state.index;
    75.                 this.ctx.strokeStyle = this.state.strokeStyle;
    76.                 if ( this.state.old ) {
    77.                     this.ctx.beginPath();
    78.                     this.ctx.moveTo( this.state.old.x, this.state.old.y );
    79.                     this.ctx.lineTo( pos.x, pos.y );
    80.                     this.ctx.stroke();
    81.                 }
    82.                 this.state.old = pos;
    83.                 if ( this.state.undopath[index] ) {
    84.                     this.state.undopath[index].push( { x: this.state.old.x, y: this.state.old.y } );
    85.                 } else {
    86.                     this.state.undopath[index] = [{
    87.                         x: this.state.old.x,
    88.                         y: this.state.old.y,
    89.                         strokeStyle: this.ctx.strokeStyle,
    90.                         lineWidth: this.ctx.lineWidth
    91.                     }];
    92.                 }
    93.             }
    94.         }, {
    95.             key: 'onEnd',
    96.             value: function onEnd () {
    97.                 this.state.old = void 0;
    98.                 this.state.isStart = false;
    99.             }
    100.         }, {
    101.             key: 'pos',
    102.             value: function pos ( e ) {
    103.                 var x = 0,
    104.                     y = 0;
    105.                 if ( e.touches ) {
    106.                     x = e.touches[0].pageX;
    107.                     y = e.touches[0].pageY;
    108.                 } else {
    109.                     x = e.offsetX / 2;
    110.                     y = e.offsetY / 2;
    111.                 }
    112.                 return { x: x, y: y };
    113.             }
    114.         }, {
    115.             key: 'ouput',
    116.             value: function ouput () {
    117.                 // 输出图片
    118.                 return this.el.toDataURL();
    119.             }
    120.         }, {
    121.             key: 'init',
    122.             value: function init () {
    123.                 // 绑定事件
    124.                 var isTouch = this.state.isTouch;
    125.                 this.el.addEventListener( isTouch ? 'touchstart' : 'mousedown', this.onStart.bind( this ), false );
    126.                 this.el.addEventListener( isTouch ? 'touchmove' : 'mousemove', this.onMove.bind( this ), false );
    127.                 this.el.addEventListener( isTouch ? 'touchend' : 'mouseup', this.onEnd.bind( this ), false );
    128.                 this.el.addEventListener( isTouch ? 'touchcancel' : 'mouseout', this.onEnd.bind( this ), false );
    129.             }
    130.         }, {
    131.             key: 'destroyed',
    132.             value: function destroyed () {
    133.                 if ( this.el ) {
    134.                     var isTouch = this.state.isTouch;
    135.                     this.el.removeEventListener( isTouch ? 'touchstart' : 'mousedown', this.onStart.bind( this ) );
    136.                     this.el.removeEventListener( isTouch ? 'touchmove' : 'mousemove', this.onMove.bind( this ) );
    137.                     this.el.removeEventListener( isTouch ? 'touchend' : 'mouseup', this.onEnd.bind( this ) );
    138.                     this.el.removeEventListener( isTouch ? 'touchcancel' : 'mouseout', this.onEnd.bind( this ) );
    139.                 }
    140.             }
    141.         }, {
    142.             key: 'clear',
    143.             value: function clear () {
    144.                 // 清除画布
    145.                 this.state.index = -1;
    146.                 this.state.undopath = [];
    147.                 this.ctx.clearRect( 0, 0, this.el.width, this.el.height );
    148.             }
    149.         }, {
    150.             key: 'undo',
    151.             value: function undo () {
    152.                 // 撤销
    153.                 this.state.index >= 0 && --this.state.index;
    154.                 var undopath = this.state.undopath;
    155.                 this.state.undopath.pop();
    156.                 this.ctx.clearRect( 0, 0, this.el.width, this.el.height );
    157.                 if ( undopath ) {
    158.                     this.ctx.beginPath();
    159.                     for ( var z = 0; z < undopath.length; ++z ) {
    160.                         this.ctx.moveTo( undopath[z][0].x, undopath[z][0].y );
    161.                         this.ctx.lineWidth = undopath[z][0].lineWidth;
    162.                         this.ctx.strokeStyle = undopath[z][0].strokeStyle;
    163.                         for ( var i = 0; i < undopath[z].length; ++i ) {
    164.                             this.ctx.lineTo( undopath[z][i].x, undopath[z][i].y );
    165.                         }
    166.                     }
    167.                     this.ctx.stroke();
    168.                     this.ctx.closePath();
    169.                 } else {
    170.                     this.state.undopath = [];
    171.                 }
    172.             }
    173.         }] );
    174.         return Draw;
    175.     }();
    176.     return Draw;
    177. } ) ) );
    复制代码
    到此这篇关于HTML5 Canvas 实现在线签字功能的文章就介绍到这了,更多相关HTML5 Canvas在线签字内容请搜索脚本之家以前的文章或继续浏览下面的相关文章,希望大家以后多多支持脚本之家!

    来源:https://www.jb51.net/html5/941286.html
    免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?立即注册

    ×

    最新评论

    QQ Archiver 手机版 小黑屋 福建二哥 ( 闽ICP备2022004717号|闽公网安备35052402000345号 )

    Powered by Discuz! X3.5 © 2001-2023

    快速回复 返回顶部 返回列表