设为首页收藏本站
天天打卡

 找回密码
 立即注册
搜索
查看: 109|回复: 11

html5手写签名的实现示例

[复制链接]

1

主题

47

回帖

117

积分

注册会员

积分
117
发表于 2024-4-20 08:11:12 | 显示全部楼层 |阅读模式
前言

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

代码已分享至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手写签名内容请搜索脚本之家以前的文章或继续浏览下面的相关文章,希望大家以后多多支持脚本之家!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

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

×

0

主题

60

回帖

119

积分

注册会员

积分
119
发表于 2024-5-18 06:05:13 | 显示全部楼层
谢谢你分享这个信息

0

主题

39

回帖

79

积分

注册会员

积分
79
发表于 2024-5-23 09:10:01 | 显示全部楼层
6666666666

0

主题

57

回帖

115

积分

注册会员

积分
115
发表于 2024-6-27 13:28:56 | 显示全部楼层
非常感谢你的观点,让我受益良多!

1

主题

57

回帖

137

积分

注册会员

积分
137
发表于 2024-7-13 08:25:40 | 显示全部楼层
保持尊重和礼貌对待其他成员是必要的。

3

主题

64

回帖

194

积分

注册会员

积分
194
发表于 2024-10-27 22:45:14 | 显示全部楼层
666666666666

1

主题

58

回帖

140

积分

注册会员

积分
140
发表于 2024-10-28 20:47:57 | 显示全部楼层
这个话题真是有趣,我也对它感兴趣。

1

主题

54

回帖

132

积分

注册会员

积分
132
发表于 2024-11-5 05:18:01 | 显示全部楼层
嘎嘎嘎嘎嘎嘎嘎

0

主题

51

回帖

103

积分

注册会员

积分
103
发表于 2024-11-5 17:48:30 | 显示全部楼层
能给个链接吗?我想深入了解一下。

1

主题

46

回帖

116

积分

注册会员

积分
116
发表于 2024-11-6 19:16:49 | 显示全部楼层
牛逼
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|爱云论坛 - d.taiji888.cn - 技术学习 免费资源分享 ( 蜀ICP备2022010826号 )|天天打卡

GMT+8, 2024-11-24 11:55 , Processed in 0.110128 second(s), 27 queries .

Powered by i云网络 Licensed

© 2023-2028 正版授权

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