Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dynamically change lineWidth of mkpolyline

I have Map in my app in which is moving as per user location.I have successfully drawn a polyline for source and destination. Using following code

- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id < MKOverlay >)overlay{
    
    MKPolylineView *view1 = [[MKPolylineView alloc] initWithOverlay:overlay];
    
        view1.lineWidth = 27.0;
        view1.strokeColor = [UIColor colorWithRed:55.0/255.0 green:168.0/255.0 blue:219.0/255.0 alpha:1];
   
    return view1;
}

But my problem is when map is moving , mean i am changing region of map as user moves , then some times polyline is not shown good some time its show thicker than actual size as you can see in below image.

i am attaching the image below, please let me know what can i do for smooth polyline when map is moving.

enter image description here

EDIT

As Matt suggested i create a subclass of MKPolylineRenderer and implement drawMapRect method as below:

-(void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context{
    
    
    CGMutablePathRef fullPath = CGPathCreateMutable();
    BOOL pathIsEmpty = YES;
    
    //merging all the points as entire path
    for (int i=0;i< self.polyline.pointCount;i++){
        CGPoint point = [self pointForMapPoint:self.polyline.points[i]];
        if (pathIsEmpty){
            CGPathMoveToPoint(fullPath, nil, point.x, point.y);
            pathIsEmpty = NO;
        } else {
            CGPathAddLineToPoint(fullPath, nil, point.x, point.y);
        }
    }
    
    //get bounding box out of entire path.
    CGRect pointsRect = CGPathGetBoundingBox(fullPath);
    CGRect mapRectCG = [self rectForMapRect:mapRect];
    //stop any drawing logic, cuz there is no path in current rect.
    if (!CGRectIntersectsRect(pointsRect, mapRectCG))return;
    
    UIColor *darker = [UIColor blackColor];
    CGFloat baseWidth = 10 / zoomScale;
    
    // draw the dark colour thicker
    CGContextAddPath(context, self.path);
    CGContextSetStrokeColorWithColor(context, darker.CGColor);
    CGContextSetLineWidth(context, baseWidth * 1.5);
    CGContextSetLineCap(context, self.lineCap);
    CGContextStrokePath(context);
    
    // now draw the stroke color with the regular width
    CGContextAddPath(context, self.path);
    CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
    CGContextSetLineWidth(context, baseWidth);
    CGContextSetLineCap(context, self.lineCap);
    CGContextStrokePath(context);
    
    [super drawMapRect:mapRect zoomScale:zoomScale inContext:context];
}

But Same problem See below image:

enter image description here

ok, i think i got problem , my polyline is added once, but as user's speed i changing zoom level of MKMapView, zoom level is changed , but polyline width is not refresh,

SO how can i dynamically change lineWidth of mkpolyline ??

like image 936
NetDemo Avatar asked Nov 10 '14 14:11

NetDemo


2 Answers

The problem is that you are setting your lineWidth at a fixed width (a really big fixed width). This gets larger or smaller as the map is zoomed larger or smaller.

Instead, implement your own MKOverlayRenderer subclass, and override drawMapRect:zoomScale:inContext:. It receives a zoomScale parameter, and so you can adjust the width of your line to look good at what the current scale may be.

like image 170
matt Avatar answered Oct 02 '22 12:10

matt


Subclass MKPolylineRenderer and override applyStrokePropertiesToContext:atZoomScale: so that it ignores the scale, and draws lines at constant width:

@interface ConstantWidthPolylineRenderer : MKPolylineRenderer
@end

@implementation ConstantWidthPolylineRenderer

- (void)applyStrokePropertiesToContext:(CGContextRef)context
                           atZoomScale:(MKZoomScale)zoomScale
{
    [super applyStrokePropertiesToContext:context atZoomScale:zoomScale];
    CGContextSetLineWidth(context, self.lineWidth);
}

@end

Now use it and admire its smooth rendering:

- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
{
    MKPolyline *polyline = (MKPolyline *)overlay;
    ConstantWidthPolylineRenderer *renderer = [[ConstantWidthPolylineRenderer alloc] initWithPolyline:polyline];
    renderer.strokeColor = [UIColor redColor];
    renderer.lineWidth = 40;
    return renderer;
}
like image 32
Gwendal Roué Avatar answered Oct 02 '22 10:10

Gwendal Roué