1

我正在开发一个测试程序来绘制使用Catmull-Rom splines平滑的自由形式的涂鸦。(链接)请参阅 Erica Sadun出色的 Core iOS Developer's Cookbook,了解如何使用 Catmull-Rom 样条线绘制平滑曲线的“食谱”。(披露:我是萨顿博士的几本书的技术评论家。)

Sadun 博士的示例代码是用 Objective-C 编写的,它在用户跟踪手指时在输入点之间绘制一系列线段,并且只有在松开手指时才会平滑曲线。

我在 Swift 3 中重构了代码。

我还更改了算法,以便它在用户绘制时“实时”生成平滑曲线。平滑算法的输出是一系列点,这些点需要用细小的线段连接以创建平滑曲线的外观。

我将生成的“折线”转换为 aa UIBezierPath 并在我的自定义 UIView 子类的 drawRect 方法中绘制它。

我发现创建平滑曲线的数学实际上非常快。绘制一个大而复杂的UIBezierPath. 当您向要平滑的输入点数组添加一个新点时,需要更改曲线的最后一部分以创建围绕前一个控制点的平滑曲线,而不是“扭结”。

因此,最简单的做法是在每次调用 DrawRect 时绘制整个贝塞尔路径。然而,随着贝塞尔路径对象变得越来越大,应用程序花费越来越多的时间来服务drawRect(),因此跟踪用户手指的路径变得越来越迟缓,并且它从用户的运动中记录的点越来越远。

我已经实施了许多优化。其中之一是调用setNeedsDisplayInRect()(或者更确切地说setNeedsDisplay(_:),因为这是 Swift 3)仅将视图中实际已更改的一小部分标记为需要重绘。

我惊讶地发现我的drawRect()(呃,draw(_:)功能现在非常快并且不再陷入困境。

似乎UIBezierPathdrawRect() 中对象的渲染已经过优化,因此它会跳过视图“脏区域”(实际需要更新的剪辑区域)之外的部分路径。

这让我很惊讶。我希望不得不放弃使用绘图UIBezierPath并编写自定义代码来找到与当前剪辑区域相交的绘图部分,但看起来我不必这样做。

有人可以确认 Quartz 绘图优化了视图的 drawrect() 方法中 UIBezierPaths 的绘制,因此它们有效地仅渲染与当前剪贴蒙版相交的路径部分吗?

4

0 回答 0