динамически изменять ширину линии mkpolyline

В моем приложении есть карта, которая перемещается в соответствии с местоположением пользователя. Я успешно нарисовал полилинию для источника и пункта назначения. Используя следующий код

- (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;
}

Но моя проблема заключается в том, что когда карта движется, это означает, что я меняю область карты по мере перемещения пользователя, тогда иногда полилиния не отображается хорошо, иногда она отображается толще, чем фактический размер, как вы можете видеть на изображении ниже.

я прилагаю изображение ниже, пожалуйста, дайте мне знать, что я могу сделать для гладкой полилинии, когда карта движется.

введите здесь описание изображения

ИЗМЕНИТЬ

Как предложил Мэтт, я создал подкласс MKPolylineRenderer и реализовал метод drawMapRect, как показано ниже:

-(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];
}

Но та же проблема См. изображение ниже:

введите здесь описание изображения

хорошо, я думаю, у меня проблема, моя полилиния добавляется один раз, но поскольку скорость пользователя я изменяю уровень масштабирования MKMapView, уровень масштабирования изменяется, но ширина полилинии не обновляется,

Итак, как я могу динамически изменить ширину линии mkpolyline??


person NetDemo    schedule 10.11.2014    source источник
comment
Та же проблема в iOS 10 с использованием MKPolylineRenderer. Вы нашли решение для этого?   -  person Marcin Kapusta    schedule 24.10.2016
comment
Я столкнулся с той же проблемой и пока не нашел решения.   -  person Vijay Sharma    schedule 10.04.2017
comment
Я также сталкиваюсь с той же проблемой, что и любое решение для управления шириной полилинии в зависимости от увеличения или уменьшения масштаба @Kumar   -  person Jaywant Khedkar    schedule 07.12.2017
comment
На момент написания этой статьи для iOS 11.3.1 не найдено подходящего решения. Я попробовал несколько решений, предложенных на StackOverflow, но ни одно из них не сработало. Какие-нибудь Новости?   -  person Ugo Chirico    schedule 21.05.2018


Ответы (3)


Проблема в том, что вы устанавливаете lineWidth фиксированную ширину (действительно большую фиксированную ширину). Он становится больше или меньше по мере увеличения или уменьшения масштаба карты.

Вместо этого реализуйте свой собственный подкласс MKOverlayRenderer и переопределите drawMapRect:zoomScale:inContext:. Он получает параметр zoomScale, поэтому вы можете отрегулировать ширину своей линии, чтобы она хорошо выглядела в текущем масштабе.

person matt    schedule 10.11.2014
comment
Спасибо, Мэтт, за ответ. Можете ли вы просто предоставить ссылку. для реализации этого класса, я новичок в этом. - person NetDemo; 10.11.2014
comment
:thnaks за предоставление ссылки, но все же я получаю размытие такого типа, не могли бы вы исправить меня в этом. - person NetDemo; 10.11.2014

Подкласс MKPolylineRenderer и переопределите applyStrokePropertiesToContext:atZoomScale:, чтобы он игнорировал масштаб и рисовал линии с постоянной шириной:

@interface ConstantWidthPolylineRenderer : MKPolylineRenderer
@end

@implementation ConstantWidthPolylineRenderer

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

@end

Теперь используйте его и любуйтесь плавным рендерингом:

- (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;
}
person Gwendal Roué    schedule 24.08.2015
comment
Спасибо! Это сработало, но теперь проблема в том, что когда я увеличиваю или уменьшаю масштаб. Ширина линии является постоянной шириной. и это большая проблема для меня. - person Vijay Sharma; 31.03.2017
comment
Я не знаю, чувак. Может быть, ваш пользовательский рендерер знает об уровне масштабирования? Я уверен, вы разберетесь во всем. - person Gwendal Roué; 31.03.2017
comment
Извините, я не уверен, как управлять уровнем масштабирования по ширине. Но я пробовал несколько настроек в этом методе, но эти изменения lineWidth воспроизводят ту же проблему, которая была задана в этой теме. - person Vijay Sharma; 10.04.2017
comment
@Kumar Не могли бы вы найти решение для установки ширины строки в зависимости от уменьшения и увеличения масштаба. - person Jaywant Khedkar; 08.12.2017

Вам нужно использовать MKPolylineRenderer вместо MKPolylineView

- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id < MKOverlay >)overlay {
    @try {

        MKPolylineRenderer *renderer = [[[MKPolylineRenderer alloc] initWithOverlay:overlay];
        renderer.lineWidth = 27.0;
        renderer.strokeColor = [UIColor colorWithRed:55.0/255.0 green:168.0/255.0 blue:219.0/255.0 alpha:1];

        return renderer;
    }
    @catch (NSException *exception) {
        NSLog(@"exception :%@",exception.debugDescription);
    }
}

Прочтите это:

Класс MKPolylineRenderer обеспечивает визуальное представление объекта наложения MKPolyline. Этот рендерер обводит только линию; это не заполняет его. Вы можете изменить цвет и другие атрибуты рисования многоугольника, изменив свойства, унаследованные от родительского класса. Обычно вы используете этот класс как есть и не создаете его подклассы.

Из библиотеки Apple

Класс MKPolylineView обеспечивает визуальное представление объекта аннотации MKPolyline. Этот вид обводит путь, представленный аннотацией. (Этот класс не заполняет область, ограниченную путем.) Вы можете изменить цвет и другие атрибуты рисования пути, изменив свойства, унаследованные от класса MKOverlayPathView. Этот класс обычно используется как есть и не является подклассом.

Из библиотеки Apple

person Kampai    schedule 10.11.2014
comment
Спасибо за ответ, но я также поддерживаю ios6, поэтому я использовал этот метод делегата. - person NetDemo; 10.11.2014
comment
и я также использую этот mkrenderer, но он также вызывает у меня ту же проблему. - person NetDemo; 10.11.2014
comment
да. Если вы собираетесь поддерживать iOS 6, то MKOverlayRenderer недоступен. - person Kampai; 10.11.2014
comment
есть ли другой способ быстро нарисовать полилинию, значит, я видел много с -()drawMethod(), но я не реализовал, поэтому понятия не имею, можете ли вы сказать мне, это мне поможет? - person NetDemo; 10.11.2014
comment
Итак, есть ли другой способ управлять шириной строки в соответствии с уровнем масштабирования? Из вашего предложения у нас есть только линия фиксированной ширины на карте, и по мере того, как мы сжимаем больше, она исчезает из-за ширины. @ Кампай - person Vijay Sharma; 12.05.2017