【问题标题】:Efficiently draw a large scrollable area有效地绘制大的可滚动区域
【发布时间】:2018-06-25 16:40:26
【问题描述】:

我正在开发一个使用六边形网格布局的简单游戏。网格非常大(宽度和高度有几千个像素)。我需要能够在滚动视图中滚动和缩放它,并且有很多单独的六边形。我已经在 CoreGraphics 中编写了绘图代码。六边形是在他们视图的drawRect: 方法中绘制的。为每个六边形调用此绘图代码:

- (void)drawInContext:(CGContextRef)context colour:(UIColor *)colour size:(CGSize)size {
    CGFloat width = size.width;
    CGFloat height = size.height;

    CGFloat x = self.offset.x;
    CGFloat y = self.offset.y;

    CGContextMoveToPoint(context, (width/2)+x, y);
    CGContextAddLineToPoint(context, width+x, (height / 4)+y);
    CGContextAddLineToPoint(context, width+x, (height * 3 / 4)+y);
    CGContextAddLineToPoint(context, (width / 2)+x, height+y);
    CGContextAddLineToPoint(context, x, (height * 3 / 4)+y);
    CGContextAddLineToPoint(context, x, (height / 4)+y);
    CGContextClosePath(context);

    CGContextSetFillColorWithColor(context, colour.CGColor);
    CGContextSetStrokeColorWithColor(context, [[UIColor whiteColor] CGColor]);
    CGContextDrawPath(context, kCGPathFillStroke);

    NSString *text = [NSString stringWithFormat:@"I:%ld\nR:%ld\nC:%ld", self.creationIndex, self.row, self.column];
    [text drawAtPoint:CGPointMake(self.offset.x+20, self.offset.y+20) withAttributes:@{NSForegroundColorAttributeName: [UIColor blackColor], NSFontAttributeName: [UIFont systemFontOfSize:[UIFont systemFontSize]]}];
}

当需要更改时,我会在视图上调用setNeedsDisplay(例如六边形更改颜色)。问题是这似乎非常低效。地图重绘大约需要半秒钟,这让一切都变得迟缓。

我尝试了以下方法:

  • 计算滚动视图的可见矩形并只绘制它的那一部分。这会在缩放到不同的矩形时导致问题,因为仅绘制目标矩形,从而导致在滚动的部分中显示黑色空间。
  • 在六边形上设置一个标志以指示它们需要更新,并且只绘制已更改的六边形。这导致只有更改后的六边形可见,因为drawRect: 似乎在执行绘图操作之前将视图填充为黑色,而不是将之前的图像留在那里并将更改后的六边形绘制在顶部。
  • 使用 UIKit 构建六边形网格。这太慢了,因为有数百个单独的视图。

总而言之,我的问题是是否有优化 CoreGraphics 绘图的方法,或者是否有另一种更有效的绘图方法。

【问题讨论】:

    标签: ios performance uiscrollview core-graphics zooming


    【解决方案1】:

    应该不需要计算可见的矩形,这是由 UIScrollView 完成的。

    见Scrollview Programming Guide

    进一步来自class documentation:管理滚动视图中显示的内容绘制的对象应该平铺内容的子视图,这样视图就不会超过屏幕的大小。当用户在滚动视图中滚动时,此对象应根据需要添加和删除子视图。

    【讨论】:

    • 感谢您的回复 mahal。这真的很有帮助。我想计算可见矩形的原因是因为我认为如果只绘制可见部分,这可以减少处理时间。此外,从 drawRect 方法记录 rect 表明它每次都绘制所有内容,因为 rect 始终与滚动视图的内容大小相同。但是,知道它会在滚动/缩放发生时添加和删除子视图会很有帮助。事实上,将每个六边形作为一个单独的 UIView 效果会更好,性能也很好。再次感谢!
    猜你喜欢
    • 2011-04-27
    • 1970-01-01
    • 2017-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-04
    • 2012-11-11
    • 1970-01-01
    相关资源
    最近更新 更多