【问题标题】:Why is drawRect on MKOverlayRenderer slow为什么 MKOverlayRenderer 上的 drawRect 很慢
【发布时间】:2014-09-09 17:40:28
【问题描述】:

对于一个应用程序,我必须在 MKMapView 上放置一个 MKCircle 注释。但是,需要移动/调整圆圈的大小。我知道有人问过这个问题,例如Moving MKCircle in MKMapView 建议删除/添加注释以获得该行为。

但是,我认为绘图非常慢,就像这篇文章中的用户:Smooth resizing of MKCircle。由于现在有这个问题的答案,这个问题似乎使用了YHAnimatedCircleView。慢是指,当我使用 UISlider 更改圆的半径时,重绘很草率,我还可以注意到用于绘制它的图块。

我创建了一个小测试代码,覆盖了子类 MKOverlayRenderer 的 drawMapRect。代码如下:

-(void) drawMapRect:(MKMapRect)mapRect
          zoomScale:(MKZoomScale)zoomScale
          inContext:(CGContextRef)context
{
    MKCircle* circleOverlay = (MKCircle*)self.overlay;

    CLLocationCoordinate2D point = circleOverlay.coordinate;          

    CGPoint locationPoint =
        [self pointForMapPoint:MKMapPointForCoordinate(point)];

    CGFloat radius =
        MKMapPointsPerMeterAtLatitude(circleOverlay.coordinate.latitude) *
        circleOverlay.radius;

    CGRect circleRect = CGRectMake(locationPoint.x - radius,
                                   locationPoint.y - radius,
                                   radius * 2.0, radius * 2.0);

    CGContextSaveGState(context);    

    CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor);
    CGContextFillEllipseInRect(context, circleRect);

    CGContextRestoreGState(context);
}

当我移动 UISlider 时,旧的注释被移除,新的 MKCircle 被放置在不同的半径上,drawMapRect 方法被调用。

然而,即使是这个小例子,在调整圆的大小时也显示出草率的绘图。

问题:

  1. 上面的例子是完全正确的,还是我在绘图时做错了什么?
  2. 如果示例正确,为什么在调整圆圈大小时重绘圆圈如此缓慢/草率?

【问题讨论】:

  • 嗨@SebastianDressler,你解决了这个问题吗?我正在努力解决它,我已经尝试了一切,但似乎没有任何效果......
  • 不,我从来没有。 AFAIK 只有 YHAnimatedCircleView 可以作为参考,但出于某种原因我不喜欢它。我的解决方案是给我使用的别针上色。

标签: ios objective-c mkmapview core-graphics


【解决方案1】:

我在 MKMapView 上绘制叠加层时遇到了类似的问题,我的问题是移动我绘制的与地图相关的圆圈。这导致地图的移动与圆圈中的移动相比存在滞后问题,看起来好像圆圈在地图顶部滑动,而不是固定在地图上。

我的解决方案是使用CADisplayLink 来同步 MKMapView 的绘图和我添加到其中的任何视图。我相信这将适用于您使用 UISlider 更改圆的半径的原始实现,但是如果没有实现,我无法彻底测试。

一个代码示例是这样的:

- (void)viewDidLoad {
    self.mapUpdateLink = [CADisplayLink displayLinkWithTarget:self
                                                 selector:@selector(updateMapView)];
    [self.mapUpdateLink addToRunLoop:[NSRunLoop mainRunLoop]
                             forMode:NSRunLoopCommonModes];
}

- (void)updateMapView {
    CGPoint centerPoint = [self.mapView convertCoordinate:self.circleView.centerCoordinate
                                            toPointToView:self.view];
    if (!isnan(centerPoint.x) && !isnan(centerPoint.y)) {
        self.circleView.center = centerPoint;
    }
}

我希望这可以帮助您解决问题。

【讨论】:

    【解决方案2】:

    据我所知,MKMapView 中的 drawRect 非常慢。 (作为好奇的人发了CCHMapClusterControlleralso found out that)

    我要做的是生成一个 UIImage 而不是绘制矩形:

    UIImage *circle;
    
    CGRect circleRect = CGRectMake(locationPoint.x - radius,
                                   locationPoint.y - radius,
                                   radius * 2.0, radius * 2.0);
    
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(radius * 2.0, radius * 2.0), NO, 0.0f);
    
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextSaveGState(ctx);
    
    
    
    CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor);
    CGContextFillEllipseInRect(context, circleRect);
    
    CGContextRestoreGState(ctx); 
      circle = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    

    您可以在 AnnotationView 的 layoutSubViews 中生成该图像(很像链接显示的:))。 AnnotationView 可以有一个半径,而 UISlider 会改变半径。在您的 setRadius 属性中,您调用 setNeedsLayout。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-04
      • 2018-08-11
      • 1970-01-01
      • 2019-10-02
      • 2010-10-30
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多