2013-12-16 4 views
9

Я использую API-интерфейс iOS 7 MapKit для создания 3D-движений камеры на карте, которая отображает путь, созданный MKDirectionsRequest. Путь оказывает MKOverlayRenderer следующим образом:MKPolylineRenderer создает зубчатые, неравные пути

-(void)showRoute:(MKDirectionsResponse *)response 
{ 
for (MKRoute *route in response.routes) 
{ 
    [self.map 
    addOverlay:route.polyline level:MKOverlayLevelAboveRoads]; 
} 
} 

- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id <MKOverlay>)overlay 
{ 
MKPolylineRenderer *renderer = 
[[MKPolylineRenderer alloc] initWithOverlay:overlay]; 
UIColor *mapOverlayColor = [UIColor colorWithRed:((float)22/255.0f) green:((float)126/255.0f) blue:((float)251/255.0f) alpha:0.8]; 
renderer.strokeColor = mapOverlayColor; 
renderer.lineWidth = 13.0; 
return renderer; 
} 

Это хорошо работает для одного вопроса, за исключением. Когда я увеличить или панорамирование по пути с MKMapCameras (и без них, если я просто сделать так, как пользователь), путь неровный, как показано на скриншоте:

screen shot http://f.cl.ly/items/3L0s3h0B1v113y3O2p3K/iPhone%20Dec%2015,%202013,%207%3A26%3A33%20PM.png

Я проверил, чтобы увидеть, если переключение к MKOverlayLevelAboveLabels имеет значение, но, к сожалению, результат был таким же.

Есть ли у кого-нибудь предложения относительно того, как улучшить рендеринг? Переключение на геодезический путь имеет значение, и если да, то как мне это реализовать?

+0

Переключение на MKGeodesicPolyline не отличается но он создается так же, как MKPolyline, за исключением того, что вы вызываете polylineWithXXX на MKGeodesicPolyline, однако рендерингом по-прежнему остается MKPolylineRenderer. – Anna

ответ

2

После того, как линия нарисована на карте, она не может быть повторно отображена, если пользователь увеличит масштаб. Или, если это так, он может быть повторно отображен до того, как пользователь закончит масштабирование. В этом случае ширина после масштабирования больше не будет отображать желаемую ширину в метрах. Один из способов борьбы с этим - переопределить regionDidChangeAnimated и удалить наложение и добавить его обратно.

3

Подкласс 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; 
} 
+1

это решение будет иметь только статическую ширину линии. Таким образом, будет проблема, связанная с увеличением. Когда мы увеличим линию масштабирования/пинча после уровня. – Kumar

1

MKPolylineRenderer серьезно нарушается, поскольку он не будет перерисовываться на экране и имеет ошибочную логику для вычисления его клипа, который заставляет артефакты endcap оставаться на экране. Удаление и считывание наложения ничего не сделало для меня. Попытка исправить ширину линии работает, но вы все равно столкнетесь с проблемами с конечной загрузкой с большей шириной линии. Использование опции roadSizeForZoomLevel не будет работать (lineWidth = 0)

Чтобы избавиться от артефактов endcap, которые никогда не исчезают, я использовал средство визуализации из примера примера Breadcrumb. Теперь у меня есть иногда неприемлемая проблема перерисовки при перемещении карты.

Средство для рендеринга с зерном Я думаю, что должен был быть PolylineRenderer, но кто-то сломал его. Но даже до сих пор неясно, как можно заставить экранированные перерисовываться (я не специалист по основной графике, но учитывая, что приложение с яблочными картами не проявляет этого поведения. Я уверен, что гуру может это понять.

В любом случае, если вы хотя бы хотите, чтобы средство визуализации что не оставит барахло на экране использовать рендеринга Breadcrumb. Это лучшее, что я мог найти. Если вам действительно нужен лучший макет, попробуйте googmaps

0

OK, я исправил эту проблему медленным рендерингом MKPolylineRenderer, чтобы медленно использовать. Сначала используйте Breadcrumb рендер от [Яблочный пакетик] [1] https://developer.apple.com/library/content/samplecode/Breadcrumb/Introduction/Intro.html#//apple_ref/doc/uid/DTS40010048-Intro-DontLinkElementID_2

Просто вместо того, чтобы динамически добавлять точки в CrumpPath просто добавляет ваш путь.

Во-вторых, теперь, когда вы исправили ошибку MKPolylines, вам необходимо ускорить ее, потому что она ужасно медленная.

Смотрите этот ответ на переполнение стека: https://stackoverflow.com/a/28964449/7313127

Чтобы приспособить это к «CrumbPathRenderer» просто добавить этот OBJ C код функции drawMapRect (Это просто быстрый и грязный)

статический dispatch_once_t onceToken;

dispatch_once (& onceToken,^{

CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(update)]; 

    [displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; 
}); 

Создать способ обновления визуализатора, который вызывает setNeedsDisplay

- (Недействительными) обновление {

[self setNeedsDisplay]; 

}

Я также добавляю renderer.setNeedsDisplay в (но это ы, вероятно, не требуется)

функ MAPview (_ MAPview: MKMapView, regionWillChangeAnimated анимированные: Bool)

{

crumbRenderer.setNeedsDisplay() 

}

Важное примечание: Это будет оказывать безотказно, но будет использовать 100 % ЦПУ. Поэтому, чтобы не разряжать батарею телефона и не разбивать процессор, в методе обновления сохраняются статические и только вызовы setNeedsDisplay, каждый третий раз на который ссылается ссылка на экран. Помните, что ссылка на CA-дисплей - это таймер обновления оборудования.

Если вы следуете за этим (поспешно скомпонованным) ответом, который занял у меня время, чтобы выяснить, вы будете использовать около 30% CPU и ваши пути к карте, чтобы никогда не казаться уродливыми.

Эй, яблоко, хотите исправить MKMapView?

2

MKPolyline не рисует, когда изменяется масштаб и когда регион меняется. Простое исправление ниже.

public class PolylineRenderer : MKPolylineRenderer { 

    private var displayLink: CADisplayLink! 
    private var ticks = 0 

    override public init(overlay: MKOverlay) { 
     super.init(overlay: overlay) 

     displayLink = CADisplayLink(target: self, selector:#selector(PolylineRenderer._update)) 
    displayLink.add(to: .main, forMode: .commonModes) 
    } 

    func _update() { 
     if ticks < 3 { 
      ticks+=1 
     } else { 
      ticks = 0 
     } 

     if ticks == 0 { 
      self.setNeedsDisplay() 
     } 
    } 

    deinit { 
     if displayLink != nil { 
      displayLink.invalidate() 
     } 
    } 
} 

Его довольно простой, как только вы осознаете, что его просто не рисуют достаточно быстро. Пропуск 3 тиков не убивает процессор и пока не работает.

1

Swift 3 Решение:

Создать подкласс MKPolylineRenderer

class CustomPolyline: MKPolylineRenderer { 

    override func applyStrokeProperties(to context: CGContext, atZoomScale zoomScale: MKZoomScale) { 
     super.applyStrokeProperties(to: context, atZoomScale: zoomScale) 
     UIGraphicsPushContext(context) 
     if let ctx = UIGraphicsGetCurrentContext() { 
      ctx.setLineWidth(self.lineWidth) 
     } 
    } 

} 

Затем используйте его в rendererFor MapKit делегата:

func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer { 
     let renderer = CustomPolyline(overlay: overlay) 
     renderer.strokeColor = UIColor.red 
     renderer.lineWidth = 100 
     return renderer 
} 

Ваши полилинии не пересборку после масштабирования таким образом, избегая артефактов

 Смежные вопросы

  • Нет связанных вопросов^_^