2013-12-16 18 views
9

Tôi đang sử dụng API MapKit cho iOS 7 để tạo các chuyển động camera 3D trên bản đồ hiển thị đường dẫn được tạo ra MKDirectionsRequest. Đường dẫn được hiển thị bởi MKOverlayRenderer như sau:MKPolylineRenderer tạo ra các đường lởm chởm, không cân bằng

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

Nó hoạt động tốt ngoại trừ một vấn đề. Khi tôi phóng to hoặc chảo xung quanh con đường với MKMapCameras (và nếu không có họ, nếu tôi chỉ đơn giản là làm như vậy như là người dùng), con đường là lởm chởm như trong ảnh chụp màn hình này:

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

Tôi đã thử nghiệm để xem nếu chuyển đổi để MKOverlayLevelAboveLabels tạo sự khác biệt nhưng đáng buồn là kết quả là như nhau.

Có ai có đề xuất về cách cải thiện hiển thị không? Việc chuyển sang một đường dẫn trắc địa có tạo ra sự khác biệt hay không và nếu có, tôi sẽ thực hiện điều này ở đây như thế nào?

+0

Chuyển sang MKGeodesicPolyline không tạo sự khác biệt ence nhưng nó được tạo ra theo cùng một cách như MKPolyline ngoại trừ bạn gọi polylineWithXXX trên MKGeodesicPolyline tuy nhiên trình kết xuất vẫn là MKPolylineRenderer. – Anna

Trả lời

2

khi dòng được vẽ trên bản đồ, nó có thể không được hiển thị lại nếu người dùng phóng to. Hoặc, nếu có, nó có thể được hiển thị lại trước khi người dùng hoàn tất việc thu phóng. Trong trường hợp này, chiều rộng sau khi thu phóng sẽ không còn phản ánh chiều rộng mong muốn của bạn tính theo mét. Một cách để giải quyết vấn đề này là ghi đè regionDidChangeAnimated và xóa lớp phủ và thêm lại.

3

Subclass MKPolylineRenderer và ghi đè applyStrokePropertiesToContext: atZoomScale: để nó bỏ qua các quy mô, và thu hút dòng ở chiều rộng cố định:

@interface ConstantWidthPolylineRenderer : MKPolylineRenderer 
@end 

@implementation ConstantWidthPolylineRenderer 

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

@end 

Bây giờ sử dụng nó và chiêm ngưỡng vẽ mịn của nó:

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

giải pháp này sẽ chỉ có chiều rộng đường tĩnh, Vì vậy, sẽ có một vấn đề liên quan đến zoom- Khi chúng tôi làm zoom/pinch dòng sẽ không được hiển thị sau khi một mức độ. – Kumar

1

MKPolylineRenderer bị hỏng nghiêm trọng vì nó sẽ không vẽ lại màn hình và nó có logic bị lỗi để tính toán cliprect của nó, điều này làm cho các hiện vật endcap bị bỏ lại trên màn hình. Loại bỏ và readding lớp phủ không làm gì cho tôi. Cố gắng khắc phục độ rộng của đường không hoạt động nhưng bạn vẫn sẽ gặp vấn đề về kết thúc với chiều rộng đường lớn hơn. Sử dụng tùy chọn roadSizeForZoomLevel sẽ không hoạt động (lineWidth = 0)

Để loại bỏ các tạo phẩm endcap không bao giờ biến mất, tôi đã sử dụng trình kết xuất từ ​​ứng dụng mẫu Breadcrumb. Bây giờ tôi chỉ có vấn đề về vẽ lại bản đồ khi không thể chấp nhận được.

Trình kết xuất đồ họa mà tôi nghĩ là những gì mà PolylineRenderer được cho là nhưng ai đó đã phá vỡ nó. Nhưng ngay cả vẫn không rõ ràng của nó như thế nào một trong những lực lượng sẽ rút ra offscreen (Im không phải là một chuyên gia đồ họa cốt lõi nhưng cho rằng bản đồ táo ứng dụng không thể hiện hành vi này Im chắc chắn một guru có thể con số nó ra.

Dù sao thì ít nhất bạn muốn một renderer Nếu bạn thực sự cần một bản đồ tốt hơn hãy thử googmaps

0

OK, tôi đã khắc phục vấn đề này với việc làm chậm MKPolylineRenderer hiển thị chậm. trình kết xuất từ ​​ [Mẫu đường dẫn của Apple] [1] https://developer.apple.com/library/content/samplecode/Breadcrumb/Introduction/Intro.html#//apple_ref/doc/uid/DTS40010048-Intro-DontLinkElementID_2

Chỉ cần thay vì thêm điểm động vào CrumpPath chỉ cần thêm đường dẫn của bạn.

Thứ hai, bây giờ bạn đã sửa lỗi hiển thị lỗi MKPolylines, bạn cần tăng tốc độ vì tốc độ chậm khủng khiếp.

Xem câu trả lời này trên stack overflow: https://stackoverflow.com/a/28964449/7313127

Để thích ứng này để các "CrumbPathRenderer" chỉ cần thêm này obj mã C để chức năng drawMapRect (Đây chỉ là nhanh chóng và bẩn)

dispatch_once_t tĩnh onceToken;

dispatch_once (& onceToken,^{

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

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

Tạo một phương pháp cập nhật về các renderer mà các cuộc gọi setNeedsDisplay

- (void) cập nhật {

[self setNeedsDisplay]; 

}

Tôi cũng đặt renderer.setNeedsDisplay trong (nhưng nó s có lẽ không cần thiết)

func MapView (_ MapView: MKMapView, regionWillChangeAnimated hoạt hình: Bool)

{

crumbRenderer.setNeedsDisplay() 

}

Chú ý quan trọng: Điều này sẽ làm cho hoàn hảo nhưng sẽ sử dụng 100 % CPU. Vì vậy, để không tiêu hao pin của điện thoại và thrash CPU, trong phương pháp cập nhật giữ một cuộc gọi tĩnh và chỉ setNeedsDisplay mỗi liên kết hiển thị thời gian thứ ba gọi nó. Nhớ liên kết hiển thị CA là bộ hẹn giờ làm mới phần cứng.

Nếu bạn làm theo câu trả lời này (vội vàng sáng tác), tôi sẽ sử dụng khoảng 30% CPU và đường dẫn bản đồ của bạn không bao giờ xuất hiện xấu xí.

Táo táo, muốn sửa MKMapView?

2

MKPolyline không vẽ khi thu phóng thay đổi và khi vùng thay đổi. Sửa lỗi đơn giản bên dưới.

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

Nó khá đơn giản khi bạn nhận ra nó không vẽ đủ nhanh. Bỏ qua 3 dấu tick không giết CPU và tạm biệt với các jaggies.

1

Swift 3 giải pháp:

Tạo một lớp con của 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) 
     } 
    } 

} 

Sau đó, sử dụng nó trong rendererFor MapKit đại biểu của bạn:

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

polylines của bạn sẽ không tái làm sau khi phóng to do đó tránh các hiện vật

Các vấn đề liên quan