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