MKPolyline / MKPolylineRenderer changing color without remove it
Asked Answered
A

2

7

I working around with map app, I want to ask how to change the polyline color without remove and add it again, I found this topic https://mcmap.net/q/1481304/-mkpolylinerenderer-change-color-without-removing-overlay in stackoverflow but this is not involve with my question, I did not touch the line, so no need to do with -[MKMapViewDelegate mapView:didSelectAnnotationView:]

So is it possible to do that?

EDIT: What I want to do is change the polyline color smoothly (by shading a color - sound like an animation) If you have any idea on how to animate this polyline please also tell me too. Thanks

Aquitaine answered 12/5, 2015 at 9:32 Comment(0)
D
8

Complex animations or shading/gradients will probably require creating a custom overlay renderer class.

These other answers give ideas about how to draw gradient polylines and animations will most like require a custom overlay renderer as well:

Apple's Breadcrumb sample app also has an example of a custom renderer which you may find useful.


However, if you just want to update the line's color (say from blue to red), then you may be able to do that as follows:

  1. Get a reference to the MKPolyline you want to change.
  2. Get a reference to the MKPolylineRenderer for the polyline obtained in step 1. This can be done by calling the map view's rendererForOverlay: instance method (not the same as the mapView:rendererForOverlay: delegate method.
  3. Update the renderer's strokeColor.
  4. Call invalidatePath on the renderer.

Not sure what you want but you may be able to "animate" the color going from blue to red by changing the color and calling invalidatePath gradually in timed steps.

Another important thing is to make sure the rendererForOverlay delegate method also uses the line's "current" color in case the map view calls the delegate method after you've changed the renderer's strokeColor directly.

Otherwise, after panning or zooming the map, the polyline's color will change back to whatever's set in the delegate method.

You could keep the line's current color in a class-level variable and use that in both the delegate method and the place where you want to change the line's color.

An alternative to a class-level variable (and probably better) is to either use the MKPolyline's title property to hold its color or a custom polyline overlay class (not renderer) with a color property.

Example:

@property (nonatomic, strong) UIColor *lineColor;
//If you need to keep track of multiple overlays, 
//try using a NSMutableDictionary where the keys are the 
//overlay titles and the value is the UIColor.

-(void)methodWhereYouOriginallyCreateAndAddTheOverlay
{
    self.lineColor = [UIColor blueColor];  //line starts as blue
    MKPolyline *pl = [MKPolyline polylineWithCoordinates:coordinates count:count];
    pl.title = @"test";
    [mapView addOverlay:pl];
}

-(void)methodWhereYouWantToChangeLineColor
{
    self.lineColor = theNewColor;

    //Get reference to MKPolyline (example assumes you have ONE overlay)...
    MKPolyline *pl = [mapView.overlays objectAtIndex:0];

    //Get reference to polyline's renderer...
    MKPolylineRenderer *pr = (MKPolylineRenderer *)[mapView rendererForOverlay:pl];
    pr.strokeColor = self.lineColor;
    [pr invalidatePath];
}

-(MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
{
    if ([overlay isKindOfClass:[MKPolyline class]]) {
        MKPolylineRenderer *pr = [[MKPolylineRenderer alloc] initWithPolyline:overlay];
        pr.strokeColor = self.lineColor;
        pr.lineWidth = 5;
        return pr;
    }

    return nil;
}
Dangelo answered 12/5, 2015 at 14:19 Comment(4)
Thank you for your answer, I will try tomorrow and tell you result.Aquitaine
Thank you, your answer is very clear and perfect to make thing I want. Further more, If I can ask for how to make this line change color smoothly (like adjust rgb in very tiny scale?) or made it animate changing color. (Or if this is not properly right place to ask, please ignore these and I will make more animate question)Aquitaine
Your follow-up question sounds complex. I suggest doing some research, trying something if possible, then posting another question with the details and I recommend including small drawings or screenshots of exactly what you're trying to achieve.Dangelo
Now THAT was helpful! Fetching the renderer from the mapview was the trick and I'd have no idea if it weren't for this answer thank you.Zymo
A
2

Yous hould look at MKOverlayPathRenderer method - invalidatePath.

From the doc, it says:

Call this method when a change in the path information would require you to recreate the overlay’s path. This method sets the path property to nil and tells the overlay renderer to redisplay its contents.

So, at this moment, you should be able to change your drawing color.

Apron answered 12/5, 2015 at 14:31 Comment(2)
Thank you for your answer, I will try tomorrow, now is night in my timezone.Aquitaine
Forgive me to mark the above answer as correct. Your answer also correct but the other has more clear and have an example. But I upvote your answer as well, Thank you.Aquitaine

© 2022 - 2024 — McMap. All rights reserved.