我不满意之前的结果,我被要求创建一个徒手绘制视图,在缩放时不会模糊。我可以想象的唯一方法是使用CATiledLayer
,因为否则在缩放时绘制线条时速度太慢。目前,我已将其设置为每次都会重新绘制每一行,但我想知道是否可以缓存前一行的结果(不作为像素,因为它们需要很好地扩展)在某种情况下。
我想过CGBitmapContext,但这是否意味着我需要在每次缩放后拆除并设置新的上下文?问题是在视网膜显示器上,线条画太慢(在iPad 2上它是如此),特别是在缩放时绘制。 App Store中有一个名为GoodNotes的应用程序,可以很好地证明这是可行的,并且可以顺利完成,但我无法理解他们是如何做到的。这是我到目前为止的代码(今天大部分时间的结果):
- (void)drawRect:(CGRect)rect
{
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(c, mLineWidth);
CGContextSetAllowsAntialiasing(c, true);
CGContextSetShouldAntialias(c, true);
CGContextSetLineCap(c, kCGLineCapRound);
CGContextSetLineJoin(c, kCGLineJoinRound);
//Protect the local variables against the multithreaded nature of CATiledLayer
[mLock lock];
NSArray *pathsCopy = [mStrokes copy];
for(UIBezierPath *path in pathsCopy) //**Would like to cache these**
{
CGContextAddPath(c, path.CGPath);
CGContextStrokePath(c);
}
if(mCurPath)
{
CGContextAddPath(c, mCurPath.CGPath);
CGContextStrokePath(c);
}
CGRect pathBounds = mCurPath.bounds;
if(pathBounds.size.width > 32 || pathBounds.size.height > 32)
{
[mStrokes addObject:mCurPath];
mCurPath = [[UIBezierPath alloc] init];
}
[mLock unlock];
}
分析显示迄今为止最热门的功能是GCSFillDRAM8by1
答案 0 :(得分:1)
首先,由于路径描边是最昂贵的操作,因此不应该锁定它,因为这会阻止您在不同的内核上同时绘制切片。
其次,我认为你可以通过在上下文中添加所有路径并完全抚摸它们来避免多次调用CGContextStrokePath
。
[mLock lock];
for ( UIBezierPath *path in mStrokes ) {
CGContextAddPath(c, path.CGPath);
}
if ( mCurPath ) {
CGContextAddPath(c, mCurPath.CGPath);
}
CGRect pathBounds = mCurPath.bounds;
if ( pathBounds.size.width > 32 || pathBounds.size.height > 32 )
{
[mStrokes addObject:mCurPath];
mCurPath = [[UIBezierPath alloc] init];
}
[mLock unlock];
CGContextStrokePath(c);
CGContextRef
只是一个用于绘图操作的画布。您无法缓存它,但您可以使用路径的展平位图图像创建CGImageRef
并重复使用该图像。这对缩放没有帮助(因为您需要在细节级别更改时重新创建图像),但在用户绘制非常长的路径时可以提高性能。
关于该主题,有一个非常有趣的WWDC 2012会议视频:Optimizing 2D Graphics and Animation Performance。
答案 1 :(得分:1)
瓶颈实际上就是我使用CATiledLayer的方式。我想用手绘信息更新太多了。我在网上的文档和教程中看到了详细程度的设置,但最后我并不需要那么多。我只是连接了scrollview委托,在完成缩放时清除了内容并更改了图层的contentScale
以匹配滚动视图。结果是美丽的(它消失并消失,但这无法帮助)。