首页 > 解决方案 > 有什么方法可以在不闪烁或闪烁的情况下使用 MKUserLocation 移动 MKCircle 叠加层?

问题描述

目前,我正在使用此代码来绘制圆圈。

func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
    if let overlay = overlay as? MKCircle {
        let circleRenderer = MKCircleRenderer(overlay: overlay)
        circleRenderer.fillColor = UIColor.black.withAlphaComponent(0.19)
        circleRenderer.lineWidth = 1
        return circleRenderer
    }
    return MKOverlayRenderer(overlay: overlay)
}

func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
    let circle = MKCircle(center: userLocation.coordinate, radius: self.regionRadius)
    print("\(userLocation.coordinate)")

    if (CLLocationManager.authorizationStatus() == .denied || CLLocationManager.authorizationStatus() == .notDetermined)  {
        mapView.removeOverlays(mapView.overlays)
    } else {
        mapView.removeOverlays(mapView.overlays)
        mapView.addOverlay(circle)
    }
}

电流输出:

在此处输入图像描述

它工作正常,但圆圈在闪烁和闪烁。我需要圆的平滑运动。我知道这是 iOS 13 的问题。

标签: swiftmkmapviewswift5

解决方案


有两种选择:

  1. 我发现,一般来说,如果在删除旧的覆盖之前添加新的覆盖,闪烁效果会减弱。

  2. 您可能会考虑使圆圈成为自定义注释视图而不是叠加层。这样,您可以只调整coordinate而不添加/删除。

通过将圆圈放在注释中,它本身是无缝的,两者都具有用户跟踪:

在此处输入图像描述

我在中途关闭了用户跟踪,所以你可以看到这两种模式。

class CirclePointerAnnotationView: MKAnnotationView {
    let circleShapeLayer: CAShapeLayer = {
        let shapeLayer = CAShapeLayer()
        shapeLayer.fillColor = UIColor.lightGray.withAlphaComponent(0.25).cgColor
        shapeLayer.strokeColor = UIColor.clear.cgColor
        return shapeLayer
    }()

    let pinShapeLayer: CAShapeLayer = {
        let shapeLayer = CAShapeLayer()
        shapeLayer.fillColor = UIColor.blue.cgColor
        shapeLayer.strokeColor = UIColor.clear.cgColor
        return shapeLayer
    }()

    let imageView: UIImageView = {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFill
        imageView.image = UIImage(named: "woman")
        imageView.clipsToBounds = true
        return imageView
    }()

    var pinHeight: CGFloat = 100
    var pinRadius: CGFloat = 30
    var annotationViewSize = CGSize(width: 300, height: 300)

    override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
        super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)

        layer.addSublayer(circleShapeLayer)
        layer.addSublayer(pinShapeLayer)
        addSubview(imageView)

        bounds.size = annotationViewSize
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func layoutSubviews() {
        let radius = min(bounds.width, bounds.height) / 2
        let center = CGPoint(x: bounds.midX, y: bounds.midY)
        circleShapeLayer.path = UIBezierPath(arcCenter: center, radius: radius, startAngle: 0, endAngle: 2 * .pi, clockwise: true).cgPath

        let angle = asin(pinRadius / (pinHeight - pinRadius))
        let pinCenter = CGPoint(x: center.x, y: center.y - (pinHeight - pinRadius))
        let path = UIBezierPath()
        path.move(to: center)
        path.addArc(withCenter: pinCenter, radius: pinRadius, startAngle: .pi - angle, endAngle: angle, clockwise: true)
        path.close()
        pinShapeLayer.path = path.cgPath

        let imageViewDimension = pinRadius * 2 - 15
        imageView.bounds.size = CGSize(width: imageViewDimension, height: imageViewDimension)
        imageView.center = pinCenter
        imageView.layer.cornerRadius = imageViewDimension / 2
    }
}

推荐阅读