如何为 Mapview iOS 中添加的 MKOverlayRenderer 设置动画?

How to animate MKOverlayRenderer added in Mapview iOS?

我有一个地图视图,如下所示

地图中绘制的线条使用的是MKPolyline。我使用苹果 MapKit 框架来显示我的地图。我的要求是当用户在 Polyline 上选择注释时,折线应显示如下所示的方向

如何在我的地图视图中显示动画? MKOverlayRenderer 继承自 NSObject,无法使用 UIView Animation 进行动画处理。我找到了一些 link here ,它在 objective C 中用于 iOS 7,是否可以在 swift 中做同样的事情?

https://github.com/jhurray/iOS7AnimatedMapOverlay

以上 link 对您有用 或以下代码。

- (void)mapView:(MKMapView *)mapView didAddOverlayRenderers:(NSArray *)renderers
{
    // Iterate through all overlayRenderers
    for (MKOverlayRenderer *overlayRenderer in renderers)
    {
        // MKPolylineRenderer
        // Animate a 'fade'
        if ([overlayRenderer isKindOfClass:[MKPolylineRenderer class]])
        {
            // Get MKPolylineRenderer
            MKPolylineRenderer *polylineRenderer = (MKPolylineRenderer *)overlayRenderer;

            // Let's manually set alpha to 0
            polylineRenderer.alpha = 0.0f;

            // Animate it back to 1
            dispatch_async(dispatch_get_main_queue(), ^{
                [UIView animateWithDuration:0.4 animations:^{
                    polylineRenderer.alpha = 1.0f
                }];
            });
        }
    }
}

谢谢

MKOverlayRender 继承自NSObject。因此,无法按照 sample project 中的说明将 CAlayer 添加到 MKOverlayRenderer。我得到以下动画效果的步骤是

  1. Subclass MKOverlayRenderer 并添加自定义图像作为地图上的叠加层

    class MapOverlayView: MKOverlayRenderer {

    var overlayImage: UIImage
    var angle: CGFloat
    
    init(overlay: MKOverlay, overlayImage:UIImage, angle: CGFloat) {
        self.overlayImage = overlayImage
        self.angle = angle
        super.init(overlay: overlay)
    }
    
    override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
    
        let mapImage = overlayImage.cgImage
        let mapRect = rect(for: overlay.boundingMapRect)
    
        // Calculate centre point on which image should be rotated
        let centerPoint = CGPoint(x: mapRect.midX, y: mapRect.midY)
    
        let a = sqrt(pow(centerPoint.x, 2.0) + pow(centerPoint.y, 2.0))
    
        let sub1 = (centerPoint.y / a) * cos(angle / 2.0)
        let sub2 = (centerPoint.x / a) * sin(angle / 2.0)
        let deltaX = -2 * a * sin((0 - angle) / 2.0) * (sub1 + sub2)
    
        let sub3 = (centerPoint.x / a) * cos(angle / 2.0)
        let sub4 = (centerPoint.y / a) * sin(angle / 2.0)
        let deltaY = 2 * a * sin((0 - angle) / 2.0) * (sub3 - sub4)
    
        context.translateBy(x: deltaX, y: deltaY)
        context.rotate(by: angle)
        context.draw(mapImage!, in: mapRect)
    }
    

    }

    class MapOverlay: NSObject, MKOverlay {

    var coordinate: CLLocationCoordinate2D
    var boundingMapRect: MKMapRect
    var identifier: String?
    
    init(identifier:String, coord: CLLocationCoordinate2D, rect: MKMapRect) {
        self.coordinate = coord
        self.boundingMapRect = rect
        self.identifier = identifier
    }
    

    }

  2. 调用计时器来更改添加的叠加层的 alpha 值

    var 计时器 = 计时器 () timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(self.toggle), userInfo: nil, repeats: true)

更改叠加渲染器的 alpha 的函数

func changeAlphaValue(identifier: String) {
        let overlays = self.mapView.overlays
        let tag: String = identifier
        for overlay in overlays {
            if let overlay = overlay as? MapOverlay {
                let identifier = overlay.identifier
                if identifier == tag {
                    let renderer = mapView.renderer(for: overlay)
                    DispatchQueue.main.async{
                        renderer?.alpha = 1.0
                    }
                }
                else {
                    let renderer = mapView.renderer(for: overlay)
                    DispatchQueue.main.async{
                        renderer?.alpha = 0.0
                    }
                }
            }
        }
    }

这将在地图上显示以下动画

该项目可在 GitHub - link