Smooth resizing of MKCircle

风格不统一 提交于 2020-01-30 04:27:45

问题


How can I achieve a smooth resizing of a MKCircleView on a UIMapView when adjusting an NSSlider? Apple has managed to do it in the Find my friends app when creating geofences (http://reviewznow.com/wp-content/uploads/2013/03/find-my-friends-location-alerts-01.jpg), so I guess it's possible in some way. So far I've tried the following solutions, but with a very "flickery" result:

First attempt

I added a new MKCircleView with an updated radius and immediately after removing the one that was (as suggested here MKOverlay not resizing smoothly) when the slider changed value. I also tried the other way around: first removing the overlay then adding a new one, but with the same "flickery" result.

- (void)sliderChanged:(UISlider*)sender
{
    double radius = (sender.value * 100);
    [self addCircleWithRadius:radius];
    [mapView removeOverlays:[self.mapView.overlays firstObject]];
}

Second attempt

In the linked SO answer, he suggests that NSOperation could be used to "help you create the MKCircle objects faster" and thus making the resizing smoother using the above method of adding/removing overlays when the slides changes value. I did a implementation where I start a new thread whenever the slider changes. In each thread I remove all old overlays and add a new one with the updated scale. Perhaps he has some other kind of implementation in mind, because the way I did it I still get the same flicker when changing the slider.

- (void)sliderChanged:(UISlider*)sender
{
     NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
                                                                             selector:@selector(updateOverlayWithScale:)
                                                                               object:[NSNumber numberWithFloat:sender.scale]];
     [self.queue addOperation:operation];
}

The method that runs i each thread:

- (void)updateOverlayWithScale:(NSNumber *)scale
{
    MKCircle *circle = [MKCircle circleWithCenterCoordinate:self.currentMapPin.coordinate
                                                     radius:100*[scale floatValue]];


    [self.mapView performSelectorOnMainThread:@selector(removeOverlays:) withObject:self.mapView.overlays waitUntilDone:NO];
    [self.mapView performSelectorOnMainThread:@selector(addOverlay:) withObject:circle waitUntilDone:NO];
}

Third attempt

I also tried implementing my own subclass of MKOverlayView that draws itself based on its scale property. Whenever the slider changes I call setNeedsDisplay and let it redraw itself, but I get the same flicker.

- (void)sliderChanged:(UISlider*)sender
{
     self.currentOverlayView.scale = sender.scale
     [self.currentOverlayView setNeedsDisplay];
}

And in my custom overlay view I implement drawMapRect:zoomScale:inContext:(CGContextRef)context like this

- (void)drawMapRect:(MKMapRect)mapRect
          zoomScale:(MKZoomScale)zoomScale
          inContext:(CGContextRef)context
{
     double radius = [(MKCircle *)[self overlay] radius];
     radius *= self.scale;

     // ... Create a rect using the updated radius and draw a circle inside it using CGContextAddEllipseInRect ...

}

So, do you have any ideas? Thanks in advance!


回答1:


A few months ago I stumbled upon this animated MKCircleView. It also has a demo on git. So I guess you should give it a go! Check it out as you might be able to tweak it to your needs with a slider etc.

Credits go to yickhong for providing this YHAnimatedCircleView



来源:https://stackoverflow.com/questions/17571332/smooth-resizing-of-mkcircle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!