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

    html5手写签名的实现示例

    发布者: 404号房间 | 发布时间: 2025-6-16 12:19| 查看数: 65| 评论数: 0|帖子模式

    前言

    业务中需要用户进行签字,如何让用户在手机端进行签字?
    示例如下

    代码已分享至Gitee: https://gitee.com/lengcz/qianming
    H5实现手写签字

    创建一个html页面
    1. <!DOCTYPE html>
    2. <html lang="en">
    3. <head>
    4.     <meta charset="utf-8">
    5.     <!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame
    6.        Remove this if you use the .htaccess -->
    7.     <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    8.     <meta name="viewport" content="initial-scale=1.0, target-densitydpi=device-dpi" /><!-- this is for mobile (Android) Chrome -->
    9.     <meta name="viewport" content="initial-scale=1.0, width=device-height"><!--  mobile Safari, FireFox, Opera Mobile  -->
    10.     <script src="/js/modernizr.js"></script>
    11.     <!--[if lt IE 9]>
    12.     <script type="text/javascript" src="libs/flashcanvas.js"></script>
    13.     <![endif]-->
    14.     <style type="text/css">
    15.         div {
    16.             margin-top:1em;
    17.             margin-bottom:1em;
    18.         }
    19.         input {
    20.             padding: .5em;
    21.             margin: .5em;
    22.         }
    23.         select {
    24.             padding: .5em;
    25.             margin: .5em;
    26.         }
    27.         #signatureparent {
    28.             color:darkblue;
    29.             background-color:darkgrey;
    30.             /*max-width:600px;*/
    31.             padding:20px;
    32.         }
    33.         /*This is the div within which the signature canvas is fitted*/
    34.         #signature {
    35.             border: 2px dotted black;
    36.             background-color:lightgrey;
    37.         }
    38.         /* Drawing the 'gripper' for touch-enabled devices */
    39.         html.touch #content {
    40.             float:left;
    41.             width:92%;
    42.         }
    43.         html.touch #scrollgrabber {
    44.             float:right;
    45.             width:4%;
    46.             margin-right:2%;
    47.             background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAFCAAAAACh79lDAAAAAXNSR0IArs4c6QAAABJJREFUCB1jmMmQxjCT4T/DfwAPLgOXlrt3IwAAAABJRU5ErkJggg==)
    48.         }
    49.         html.borderradius #scrollgrabber {
    50.             border-radius: 1em;
    51.         }
    52.     </style>
    53. </head>
    54. <body>
    55. <div>
    56.     <div id="content">
    57.         <div id="signatureparent">
    58.             <div>jSignature inherits colors from parent element. Text = Pen color. Background = Background. (This works even when Flash-based Canvas emulation is used.)</div>
    59.             <div id="signature"></div></div>
    60.         <div id="tools"></div>
    61.         <div><p>Display Area:</p><div id="displayarea"></div></div>
    62.     </div>
    63.     <div id="scrollgrabber"></div>
    64. </div>
    65. <script src="/js/jquery-3.2.1.min.js"></script>
    66. <script type="text/javascript">
    67.     jQuery.noConflict()
    68. </script>
    69. <script>
    70.     /*  @preserve
    71.     jQuery pub/sub plugin by Peter Higgins (dante@dojotoolkit.org)
    72.     Loosely based on Dojo publish/subscribe API, limited in scope. Rewritten blindly.
    73.     Original is (c) Dojo Foundation 2004-2010. Released under either AFL or new BSD, see:
    74.     http://dojofoundation.org/license for more information.
    75.     */
    76.     (function($) {
    77.         var topics = {};
    78.         $.publish = function(topic, args) {
    79.             if (topics[topic]) {
    80.                 var currentTopic = topics[topic],
    81.                     args = args || {};
    82.                 for (var i = 0, j = currentTopic.length; i < j; i++) {
    83.                     currentTopic[i].call($, args);
    84.                 }
    85.             }
    86.         };
    87.         $.subscribe = function(topic, callback) {
    88.             if (!topics[topic]) {
    89.                 topics[topic] = [];
    90.             }
    91.             topics[topic].push(callback);
    92.             return {
    93.                 "topic": topic,
    94.                 "callback": callback
    95.             };
    96.         };
    97.         $.unsubscribe = function(handle) {
    98.             var topic = handle.topic;
    99.             if (topics[topic]) {
    100.                 var currentTopic = topics[topic];
    101.                 for (var i = 0, j = currentTopic.length; i < j; i++) {
    102.                     if (currentTopic[i] === handle.callback) {
    103.                         currentTopic.splice(i, 1);
    104.                     }
    105.                 }
    106.             }
    107.         };
    108.     })(jQuery);
    109. </script>
    110. <script src="/js/jSignature.min.noconflict.js"></script>
    111. <script>
    112.     (function($){
    113.         $(document).ready(function() {
    114.             // This is the part where jSignature is initialized.
    115.             var $sigdiv = $("#signature").jSignature({'UndoButton':true})
    116.                 // All the code below is just code driving the demo.
    117.                 , $tools = $('#tools')
    118.                 , $extraarea = $('#displayarea')
    119.                 , pubsubprefix = 'jSignature.demo.'
    120.             var export_plugins = $sigdiv.jSignature('listPlugins','export')
    121.                 , chops = ['<span><b>提取签名数据: </b></span><select>','<option value="">(select export format)</option>']
    122.                 , name
    123.             for(var i in export_plugins){
    124.                 if (export_plugins.hasOwnProperty(i)){
    125.                     name = export_plugins[i]
    126.                     chops.push('<option value="' + name + '">' + name + '</option>')
    127.                 }
    128.             }
    129.             chops.push('</select><span><b> or: </b></span>')
    130.             $(chops.join('')).bind('change', function(e){
    131.                 if (e.target.value !== ''){
    132.                     var data = $sigdiv.jSignature('getData', e.target.value)
    133.                     $.publish(pubsubprefix + 'formatchanged')
    134.                     if (typeof data === 'string'){
    135.                         $('textarea', $tools).val(data)
    136.                     } else if($.isArray(data) && data.length === 2){
    137.                         $('textarea', $tools).val(data.join(','))
    138.                         $.publish(pubsubprefix + data[0], data);
    139.                     } else {
    140.                         try {
    141.                             $('textarea', $tools).val(JSON.stringify(data))
    142.                         } catch (ex) {
    143.                             $('textarea', $tools).val('Not sure how to stringify this, likely binary, format.')
    144.                         }
    145.                     }
    146.                 }
    147.             }).appendTo($tools)
    148.             $('<input type="button" value="Reset">').bind('click', function(e){
    149.                 $sigdiv.jSignature('reset')
    150.             }).appendTo($tools)
    151.             $('<div><textarea style="width:100%;height:7em;"></textarea></div>').appendTo($tools)
    152.             $.subscribe(pubsubprefix + 'formatchanged', function(){
    153.                 $extraarea.html('')
    154.             })
    155.             $.subscribe(pubsubprefix + 'image/svg+xml', function(data) {
    156.                 try{
    157.                     var i = new Image()
    158.                     i.src = 'data:' + data[0] + ';base64,' + btoa( data[1] )
    159.                     $(i).appendTo($extraarea)
    160.                 } catch (ex) {
    161.                 }
    162.                 var message = [
    163.                     "If you don't see an image immediately above, it means your browser is unable to display in-line (data-url-formatted) SVG."
    164.                     , "This is NOT an issue with jSignature, as we can export proper SVG document regardless of browser's ability to display it."
    165.                     , "Try this page in a modern browser to see the SVG on the page, or export data as plain SVG, save to disk as text file and view in any SVG-capabale viewer."
    166.                 ]
    167.                 $( "<div>" + message.join("<br/>") + "</div>" ).appendTo( $extraarea )
    168.             });
    169.             $.subscribe(pubsubprefix + 'image/svg+xml;base64', function(data) {
    170.                 var i = new Image()
    171.                 i.src = 'data:' + data[0] + ',' + data[1]
    172.                 $(i).appendTo($extraarea)
    173.                 var message = [
    174.                     "If you don't see an image immediately above, it means your browser is unable to display in-line (data-url-formatted) SVG."
    175.                     , "This is NOT an issue with jSignature, as we can export proper SVG document regardless of browser's ability to display it."
    176.                     , "Try this page in a modern browser to see the SVG on the page, or export data as plain SVG, save to disk as text file and view in any SVG-capabale viewer."
    177.                 ]
    178.                 $( "<div>" + message.join("<br/>") + "</div>" ).appendTo( $extraarea )
    179.             });
    180.             $.subscribe(pubsubprefix + 'image/png;base64', function(data) {
    181.                 var i = new Image()
    182.                 i.src = 'data:' + data[0] + ',' + data[1]
    183.                 $('<span><b>As you can see, one of the problems of "image" extraction (besides not working on some old Androids, elsewhere) is that it extracts A LOT OF DATA and includes all the decoration that is not part of the signature.</b></span>').appendTo($extraarea)
    184.                 $(i).appendTo($extraarea)
    185.             });
    186.             $.subscribe(pubsubprefix + 'image/jsignature;base30', function(data) {
    187.                 $('<span><b>This is a vector format not natively render-able by browsers. Format is a compressed "movement coordinates arrays" structure tuned for use server-side. The bonus of this format is its tiny storage footprint and ease of deriving rendering instructions in programmatic, iterative manner.</b></span>').appendTo($extraarea)
    188.             });
    189.             if (Modernizr.touch){
    190.                 $('#scrollgrabber').height($('#content').height())
    191.             }
    192.         })
    193.     })(jQuery)
    194. </script>
    195. </body>
    196. </html>
    复制代码
    modernizr.js
    1. /* Modernizr 2.5.2 (Custom Build) | MIT & BSD
    2. * Build: http://www.modernizr.com/download/#-borderradius-csscolumns-canvas-touch-mq-cssclasses-addtest-teststyles-testprop-testallprops-prefixes-domprefixes-fullscreen_api
    3. */
    4. ;window.Modernizr = function(a, b, c) {
    5.     function A(a) {
    6.         j.cssText = a
    7.     }
    8.     function B(a, b) {
    9.         return A(m.join(a + ";") + (b || ""))
    10.     }
    11.     function C(a, b) {
    12.         return typeof a === b
    13.     }
    14.     function D(a, b) {
    15.         return !!~("" + a).indexOf(b)
    16.     }
    17.     function E(a, b) {
    18.         for (var d in a)
    19.             if (j[a[d]] !== c)
    20.                 return b == "pfx" ? a[d] : !0;
    21.         return !1
    22.     }
    23.     function F(a, b, d) {
    24.         for (var e in a) {
    25.             var f = b[a[e]];
    26.             if (f !== c)
    27.                 return d === !1 ? a[e] : C(f, "function") ? f.bind(d || b) : f
    28.         }
    29.         return !1
    30.     }
    31.     function G(a, b, c) {
    32.         var d = a.charAt(0).toUpperCase() + a.substr(1)
    33.             , e = (a + " " + o.join(d + " ") + d).split(" ");
    34.         return C(b, "string") || C(b, "undefined") ? E(e, b) : (e = (a + " " + p.join(d + " ") + d).split(" "),
    35.             F(e, b, c))
    36.     }
    37.     var d = "2.5.2", e = {}, f = !0, g = b.documentElement, h = "modernizr", i = b.createElement(h), j = i.style, k, l = {}.toString, m = " -webkit- -moz- -o- -ms- ".split(" "), n = "Webkit Moz O ms", o = n.split(" "), p = n.toLowerCase().split(" "), q = {}, r = {}, s = {}, t = [], u = t.slice, v, w = function(a, c, d, e) {
    38.         var f, i, j, k = b.createElement("div"), l = b.body, m = l ? l : b.createElement("body");
    39.         if (parseInt(d, 10))
    40.             while (d--)
    41.                 j = b.createElement("div"),
    42.                     j.id = e ? e[d] : h + (d + 1),
    43.                     k.appendChild(j);
    44.         return f = ["&#173;", "<style>", a, "</style>"].join(""),
    45.             k.id = h,
    46.             m.innerHTML += f,
    47.             m.appendChild(k),
    48.         l || g.appendChild(m),
    49.             i = c(k, a),
    50.             l ? k.parentNode.removeChild(k) : m.parentNode.removeChild(m),
    51.             !!i
    52.     }, x = function(b) {
    53.         var c = a.matchMedia || a.msMatchMedia;
    54.         if (c)
    55.             return c(b).matches;
    56.         var d;
    57.         return w("@media " + b + " { #" + h + " { position: absolute; } }", function(b) {
    58.             d = (a.getComputedStyle ? getComputedStyle(b, null) : b.currentStyle)["position"] == "absolute"
    59.         }),
    60.             d
    61.     }, y = {}.hasOwnProperty, z;
    62.     !C(y, "undefined") && !C(y.call, "undefined") ? z = function(a, b) {
    63.             return y.call(a, b)
    64.         }
    65.         : z = function(a, b) {
    66.             return b in a && C(a.constructor.prototype[b], "undefined")
    67.         }
    68.         ,
    69.     Function.prototype.bind || (Function.prototype.bind = function(b) {
    70.             var c = this;
    71.             if (typeof c != "function")
    72.                 throw new TypeError;
    73.             var d = u.call(arguments, 1)
    74.                 , e = function() {
    75.                 if (this instanceof e) {
    76.                     var a = function() {};
    77.                     a.prototype = c.prototype;
    78.                     var f = new a
    79.                         , g = c.apply(f, d.concat(u.call(arguments)));
    80.                     return Object(g) === g ? g : f
    81.                 }
    82.                 return c.apply(b, d.concat(u.call(arguments)))
    83.             };
    84.             return e
    85.         }
    86.     );
    87.     var H = function(c, d) {
    88.         var f = c.join("")
    89.             , g = d.length;
    90.         w(f, function(c, d) {
    91.             var f = b.styleSheets[b.styleSheets.length - 1]
    92.                 , h = f ? f.cssRules && f.cssRules[0] ? f.cssRules[0].cssText : f.cssText || "" : ""
    93.                 , i = c.childNodes
    94.                 , j = {};
    95.             while (g--)
    96.                 j[i[g].id] = i[g];
    97.             e.touch = "ontouchstart"in a || a.DocumentTouch && b instanceof DocumentTouch || (j.touch && j.touch.offsetTop) === 9
    98.         }, g, d)
    99.     }([, ["@media (", m.join("touch-enabled),("), h, ")", "{#touch{top:9px;position:absolute}}"].join("")], [, "touch"]);
    100.     q.canvas = function() {
    101.         var a = b.createElement("canvas");
    102.         return !!a.getContext && !!a.getContext("2d")
    103.     }
    104.         ,
    105.         q.touch = function() {
    106.             return e.touch
    107.         }
    108.         ,
    109.         q.borderradius = function() {
    110.             return G("borderRadius")
    111.         }
    112.         ,
    113.         q.csscolumns = function() {
    114.             return G("columnCount")
    115.         }
    116.     ;
    117.     for (var I in q)
    118.         z(q, I) && (v = I.toLowerCase(),
    119.             e[v] = q[I](),
    120.             t.push((e[v] ? "" : "no-") + v));
    121.     return e.addTest = function(a, b) {
    122.         if (typeof a == "object")
    123.             for (var d in a)
    124.                 z(a, d) && e.addTest(d, a[d]);
    125.         else {
    126.             a = a.toLowerCase();
    127.             if (e[a] !== c)
    128.                 return e;
    129.             b = typeof b == "function" ? b() : b,
    130.                 g.className += " " + (b ? "" : "no-") + a,
    131.                 e[a] = b
    132.         }
    133.         return e
    134.     }
    135.         ,
    136.         A(""),
    137.         i = k = null,
    138.         e._version = d,
    139.         e._prefixes = m,
    140.         e._domPrefixes = p,
    141.         e._cssomPrefixes = o,
    142.         e.mq = x,
    143.         e.testProp = function(a) {
    144.             return E([a])
    145.         }
    146.         ,
    147.         e.testAllProps = G,
    148.         e.testStyles = w,
    149.         g.className = g.className.replace(/(^|\s)no-js(\s|$)/, "$1$2") + (f ? " js " + t.join(" ") : ""),
    150.         e
    151. }(this, this.document),
    152.     Modernizr.addTest("fullscreen", function() {
    153.         for (var a = 0; a < Modernizr._domPrefixes.length; a++)
    154.             if (document[Modernizr._domPrefixes[a].toLowerCase() + "CancelFullScreen"])
    155.                 return !0;
    156.         return !!document.cancelFullScreen || !1
    157.     });
    复制代码
    运行测试用例

    到此这篇关于html5手写签名的实现示例的文章就介绍到这了,更多相关html5手写签名内容请搜索脚本之家以前的文章或继续浏览下面的相关文章,希望大家以后多多支持脚本之家!

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

    本帖子中包含更多资源

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

    ×

    最新评论

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

    Powered by Discuz! X3.5 © 2001-2023

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