在iOS上捕捉签名

Square Engineering Blog 上有一篇很棒的文章,为 Android 带来了更流畅的签名,但我没有找到任何与 iOS 相关的介绍。所以,在 iOS 设备上捕捉用户签名的最好方式是什么呢?

虽然我没有找到关于签名捕捉的文章,但 App Store 上已有一些应用很好地实现了签名捕捉。我的目标用户体验是达到 iPad 应用 Paper by 53 那样的效果(它是一个绘图应用,有着漂亮且极具响应性的笔刷)。

本文所有的代码都可以在 Github 仓库 SignatureDemo 里找到。

点点相连

rgegfhrthr652d6469616772616d2d6c696e65732e706e67

最简单的方式是捕捉用户的触摸点并用直线将它们连接在一起。

UIView 子类的初始化方法中,创建一个 path ,以及用于捕捉触摸事件的手势识别器。

捕捉 pan 手势的触摸点,并通过连线将其放入 bézier path 里:

画出 path:

 

sdvgrhgrthrth2d6c65747465722d6a2e706e67

上图是用这种技术画出的字母 “J” ,它也揭示了一些问题:在较慢的速度下, iOS 可以捕捉到足够多的触摸点,因此看起来较平滑,但稍快的移动就会导致触摸点之间较大的间距,签名看起来就是一些直线段相连。

2012 年的 Apple 开发者大会有一个 session 叫做 创建高级手势识别器,它用了一点数学来解决此问题。

二次贝塞尔曲线

trhrehrthrtr616472617469632e706e67

作为用线段连接各触摸点的代替,我们改用二次贝塞尔曲线来连接这些点,使用前述的 WWDC session 上讨论的技术(定位到 42 分 15 秒)。用二次贝塞尔曲线来连接触摸点,使用触摸点作为控制点以及中间点作为起点和终点。

添加二次曲线到之前的代码里要求存储前一个触摸点,所以要添加一个实例变量:

并创建一个函数来计算两点的中间点:

再更新 pan 手势处理器,用二次曲线替换直线:

grefbd6a2d7175616472617469632e706e67

并没有改写太多代码,但我们已经看到了巨大的不同。触摸点不再可见,但对于捕捉签名来说,它依然有些乏味。每个曲线都是同样的宽度,这不符合实际用钢笔签名的感觉。

可变的线宽

基于触摸速度,宽度可变,这样就能创建出更加自然的笔画。 UIPanGestureRecognizer 已经包含有一个叫做 velocityInView: 的方法,它用一个 CGPoint 返回当前触摸的速度。

为了渲染出一个可变宽度的笔画,我切换到 OpenGL ES 和一个能转换笔画为三角形(具体说来,是三角带(triangle strip))的叫做镶嵌(tesselation)的技术(OpenGL 支持画线,但 iOS 不支持平滑过渡的可变宽度)。沿曲线的二次分点同样需要被计算,但这超出了本文讨论的范畴。还请看看 Github 上的源代码了解细节吧。

给定两个点,计算出一个垂直的向量,它的大小设置为当前厚度的一半。基于 GL_TRIANGLE_STRIP 的自然特性,只需要两个点就能用两个三角形去创建下一个矩形。

sdfvs676c652d73747269702e706e67

下面是使用二次贝塞尔曲线,并根据速度调节笔画粗细而创造出的一个具有视觉吸引力且非常自然的签名。

regrer6f70656e676c2e706e67

1 1 收藏 评论

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部