我正在制作一个测试程序来绘制使用Catmull-Rom splines平滑的自由形式涂鸦。 (链接)请参阅Erica Sadun的杰出 Core iOS Developer's Cookbook,了解如何使用Catmull-Rom样条曲线绘制平滑曲线的“配方”。 (披露:我是Sadun博士的几本书的技术评论员。)
博士。 Sadun的示例代码是用Objective-C编写的,当用户跟踪他们的手指时,在输入点之间绘制一系列线段,并且只有在他们释放手指时才会平滑曲线。
我在Swift 3中重构了代码。
我还更改了算法,以便在用户绘制时“生动”生成平滑曲线。平滑算法的输出是一系列点,需要与细线段连接以创建平滑曲线的外观。
我将生成的“折线”转换为UIBezierPath,并在我的自定义UIView子类的drawRect方法中绘制它。
我发现创建平滑曲线的数学实际上非常快。耗费时间的是一个庞大而复杂的UIBezierPath
。当您向要平滑的输入点数组添加新点时,需要更改曲线的最后部分以在前一个控制点周围创建平滑曲线而不是“扭结”。
因此,最简单的方法是在每次调用DrawRect时绘制整个bezier路径。然而,随着贝塞尔路径对象变大,应用程序花费越来越多的时间服务drawRect()
,因此跟踪用户手指的路径变得越来越迟缓,并且它从用户的动作中记录的点得到进一步增加进一步分开。
我已经实施了许多优化。其中一个是调用setNeedsDisplayInRect()
(或者更确切地说是setNeedsDisplay(_:)
,因为这是Swift 3),只是标记了实际需要重新绘制的视图的一小部分。
我很惊讶地发现我的drawRect()
(呃,draw(_:)
功能现在非常快,不会再陷入困境。
似乎优化了drawRect()中UIBezierPath
个对象的渲染,以便它跳过视图“脏区域”之外的部分路径(实际需要更新的剪辑区域。)
这令我感到惊讶。我希望不得不放弃使用UIBezierPath
进行绘图并编写自定义代码,找到与当前剪辑区域相交的绘图部分,但看起来我不必这样做。
有人可以确认Quartz绘图优化了视图的drawrect()方法中UIBezierPaths的绘制,因此它们只能有效地渲染与当前剪贴蒙版相交的路径部分吗?