使用 HTML5和 iPad 捕获签名

有人知道这是怎么做到的吗? 你会使用一个画布对象,svg,jQuery 等吗?

170159 次浏览

一个带有一些 JavaScript 的画布元素将非常有用。

事实上,签名本(一个 jQuery 插件)已经实现了这一点。

这是我刚刚做的 一个使用 SVG 快速修改的版本。在我的 iPhone 上很管用。也可以在桌面浏览器中使用正常的鼠标事件。

也许最好的两个浏览器技术人员是 Canvas 和 Flash 作为备份。

我们在 IE 上尝试 VML 作为 Canvas 的备份,但是它比 Flash 慢得多。SVG 比其他的都慢。

对于 jSignature (http://willowsystems.github.com/jSignature/) ,我们使用 Canvas 作为主要的参数,对于 IE8和更少的参数,则回退到基于 Flash 的 Canvas 模拟器(FlashCanvas)。我觉得这招对我们很管用。

这是另一个基于画布的可变宽度(基于绘制速度)曲线版本: 在 http://szimek.github.io/signature_pad演示和在 https://github.com/szimek/signature_pad代码。

signature sample

另一个 OpenSource 签名字段是 https://github.com/applicius/jquery.signfield/,它使用 Sketch.js 注册了 jQuery 插件。

已经列出的选项是非常好的,但是在这里更多关于这个主题,我已经研究和偶然发现。

1) http://perfectionkills.com/exploring-canvas-drawing-techniques/
2) < a href = “ http://mcc.id.au/2010/signature.html”rel = “ nofollow norefrer”> http://mcc.id.au/2010/signature.html
3) < a href = “ https://zipso.net/a-simple-touch screen-sketchpad-using-javascript-and-html5/”rel = “ nofollow noReferrer”> https://zipso.net/a-simple-touchscreen-sketchpad-using-javascript-and-html5/

像往常一样,你可以将画布保存为图像:
Http://www.html5canvastutorials.com/advanced/html5-canvas-save-drawing-as-an-image/

祝你好运,签名愉快

@ szimek (选择的答案)有一个很好的解决方案,为那些想要一个全功能的模块与麻省理工学院的许可证,是好去。@ heycam 有一个更简单的解决方案,不需要库或插件,没有许可证,可以很容易地定制; 所有这些都使它更适合我的需要。这篇文章试图解释他的解决方案到底是如何工作的。

基本工作流程:

  1. 创建一个功能性的空白 svg来包含签名
  2. 在容器 svg中保留一个 path元素
  3. 使用触摸事件(touchstarttouchmovetouchend)为用户使用触摸输入来绘制签名
  4. 使用鼠标事件(mousedownmousemovemouseupmouseout)为用户使用鼠标输入绘制签名
  5. 在每个事件中,检测输入类型(触摸、鼠标)以获得用户正在绘制的路径的 X、 Y 坐标
  6. 将每个路径追加到 path元素的 d属性(路径坐标) ,以便显示给用户
  7. 添加一个 helper 函数以输出签名路径(path.d) ,这只是一个 string,稍后您可以将其插回到 path.d中以恢复签名
  8. 添加一个 helper 函数以清除 path.d

以下是@heycam 的可运行代码片段解决方案:

//init
let r = document.getElementById('r'),
p = document.getElementById('p'),
signaturePath = '',
isDown = false,
svg = document.getElementById('sig_panel'),
b_show = document.getElementById('show'),
b_clear = document.getElementById('clear'),
pathdata = document.getElementById('pathdata');


//drawing functions
function isTouchEvent(e) {
return e.type.match(/^touch/);
}


function getCoords(e) {
if (isTouchEvent(e)) {
return e.targetTouches[0].clientX + ',' + e.targetTouches[0].clientY;
}
return e.clientX + ',' + e.clientY;
}


function down(e) {
signaturePath += 'M' + getCoords(e) + ' ';
p.setAttribute('d', signaturePath);
isDown = true;


if (isTouchEvent(e)) e.preventDefault();
}


function move(e) {
if (isDown) {
signaturePath += 'L' + getCoords(e) + ' ';
p.setAttribute('d', signaturePath);
}


if (isTouchEvent(e)) e.preventDefault();
}


function up(e) {
isDown = false;


if (isTouchEvent(e)) e.preventDefault();
}


//input handlers
r.addEventListener('touchstart', down, false);
r.addEventListener('touchmove', move, false);
r.addEventListener('touchend', up, false);
r.addEventListener('mousedown', down, false);
r.addEventListener('mousemove', move, false);
r.addEventListener('mouseup', up, false);
r.addEventListener('mouseout', up, false);


//helper functions
function clearSignature() {
pathdata.textContent = '';
signaturePath = '';
p.setAttribute('d', '');
}


function getSignature() {
pathdata.textContent = signaturePath;
return signaturePath;
}


//button handlers
b_show.addEventListener('click', getSignature);
b_clear.addEventListener('click', clearSignature);
svg {
margin: .5em;
border: 1px solid gray;
border-radius: .5em;
}


.flex {
display: flex;
}


button {
margin: .5em;
}


#pathdata {
font-family: monospace;
background: #ddd;
padding: 1em;
margin: 1em .5em;
}
<svg id="sig_panel" xmlns="http://www.w3.org/2000/svg" width="300" height="100" viewBox="0 0 300 100">
<rect id="r" width="300" height="100" fill="#ffa"/>
<line x1="0" y1="80" x2="300" y2="80" stroke="#666" stroke-width="1" stroke-dasharray="3" shape-rendering="crispEdges" pointer-events="none"/>
<path id="p" stroke="navy" stroke-width="2" fill="none" pointer-events="none"/>
</svg>
<div class="flex">
<button id="show">Show signaure path data</button>
<button id="clear">Clear signature</button>
</div>
<div id="pathdata"></div>

保存服务器(和客户端缓存)上的 path.d值是我所需要的。其他人可能需要保存整个 svg本身与 path.d填写,或转换为其他格式(JPEG,PNG,PDF)使用适当的转换器(这里不涉及)。

我计划更进一步,添加用户控件来管理以下内容:

  • 线厚度: path.stroke-width
  • 线条颜色: path.stroke
  • 线路质量: path.shape-rendering

并为签名字段设置主题(作为自定义表单 lib 的一部分) :

  • 集装箱尺寸: rect.widthrect.height
  • 集装箱背景: rect.fill
  • 消除“这里的标志”行: line