我们正在开发一个绘图应用程序。在我们绘制交叉线时,交叉点会清除之前绘制的两条线相交的像素。我们正在使用 setneedsdisplayinrect 来刷新绘图数据。
如何克服这个问题?
tl; dr:您需要存储先前的线段并在再次在同一个矩形中绘制时重新绘制它们。
我们正在使用 setneedsdisplayinrect 来刷新绘图数据
这是一件好事。你能看到这样做的任何副作用吗?如果没有,请尝试传递整个矩形,看看会发生什么。您将看到只绘制了最后一段。
现在您知道您需要存储并可能重绘以前的线段(或只是它们的图像)。
第一个也是最简单的解决方案是将所有行存储在一个数组中并重新绘制它们。您会注意到这会大大降低您的应用程序的速度,尤其是在绘制了一段时间之后。此外,仅绘制您需要的东西并不顺利
您可以通过过滤数组中的所有行以仅重绘与刷新的矩形相交的行来加速上述实现。例如,这可以通过获取线段的边界框(使用CGPathGetBoundingBox(path)
)并检查它是否与刷新的矩形相交(使用CGRectIntersectsRect(refreshRect, boundingBox)
)来完成。
这会减少一些绘图,但你仍然会得到很长的线阵列,并在一段时间后看到性能问题。
不必存储所有先前行的一种好方法是将它们绘制到位图中(一个单独的图像上下文(请参阅 参考资料UIGraphicsBeginImageContextWithOptions(...)
)),然后再绘制新的线段。但是,这几乎会使您必须这样做的绘图增加一倍,因此不应该对每一帧都进行。
您可以做的一件事是存储最后 100 个线段(或者可能是最后 1000 个或任何您自己的性能调查显示的内容,您应该自己调查这些内容)并将其余部分绘制成图像。每次有 100 条新线时,您都将它们添加到图像上下文中——首先绘制图像,然后绘制新的 100 条线——并将其保存为新图像。
您可以做的另一件事是在用户每次抬起手指时将所有新线条绘制到图像上。结合上述建议,这可以很好地工作。
根据您的应用程序的复杂性,您可能需要这些建议中的一个或多个来保持您的应用程序响应(这对于绘图应用程序非常重要),但首先进行调查,如果您不需要,不要让您的解决方案过于复杂.