swift iOS MapKit自定义用户位置标题错误

6yoyoihd  于 2022-12-10  发布在  Swift
关注(0)|答案(1)|浏览(137)

我试图使一个自定义的“用户位置”引脚,与标题旋转的基础上,用户的位置标题。
我用了这样的回答:https://stackoverflow.com/a/58363556/894671作为一个基础,并设法得到和运行一个自定义引脚,旋转的基础上,标题。

问题:

在设备上测试时,使用提供的标题进行的转换似乎不正确。只有在0/360度时才能正确显示,但如果我旋转,我会看到默认的MKMapKit显示的标题正确旋转,而我的自定义图标在同一时间内旋转了两次。
请参见随附视频:https://i.imgur.com/3PEm2MS.mp4
演示已上传到此处:https://github.com/GuntisTreulands/Demo123
但实际上,AnnotationView是这样的:

class AnnotationView : MKAnnotationView, HeadingDelegate {
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

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

    func headingChanged(_ heading: CLLocationDirection) {
        // For simplicity the affine transform is done on the view itself
        UIView.animate(withDuration: 0.1, animations: { [unowned self] in
            self.transform = CGAffineTransform(rotationAngle: CGFloat(heading * .pi / 180.0 ))
        })
    }
}

和标题从这里转发:

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
    {
        if let lastLocation = locations.last {
            userLocationAnnotation.coordinate = lastLocation.coordinate
        }
    }

我搞不懂,为什么我的定位方向这么奇怪。

vatpfxk5

vatpfxk51#

Okay, I managed to kinda solve this.
Here is the new result: https://imgur.com/a/YJ1H683
What I did was:

func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {

        if let heading = mapView.userLocation.heading {
            userLocationAnnotation.heading = -mapView.camera.heading + (heading.trueHeading > 0 ? heading.trueHeading : heading.magneticHeading)
        } else {
            userLocationAnnotation.heading = -mapView.camera.heading + (newHeading.trueHeading > 0 ? newHeading.trueHeading : newHeading.magneticHeading)
        }
    }

So - in case I am using userlocation with trackingmode == .followWithHeading, this is working great. My icon is on top of the original icon.
To hide original user icon and show yours instead - return a custom annotation view (with nothing to render) for userlocation:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {

        guard !(annotation is MKUserLocation) else {

            var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "AnnotationView")

            if annotationView == nil {
                annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "AnnotationView")
            }

            return annotationView
        }

        if let annotation = annotation as? Annotation {
            var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: NSStringFromClass(Annotation.self))
            if (annotationView == nil) {
                annotationView = AnnotationView(annotation: annotation as MKAnnotation, reuseIdentifier: NSStringFromClass(Annotation.self))
            } else {
                annotationView!.annotation = annotation as MKAnnotation
            }

                annotation.headingDelegate = annotationView as? HeadingDelegate
                annotationView!.image = UIImage.init(named: "user_pin")

            return annotationView
        }
        
        return nil
    }

Thus the result is:

1.) Get original apple maps user location + followWithHeading, but with a custom pin and correct location.
2.) I can adjust my custom location pin location to some different coordinates, but keep in mind, that followWithHeading will rotate around the real userLocation coordinates.
3.) I have also noticed, that without userlocation, the original calculation:

userLocationAnnotation.heading = -mapView.camera.heading + (newHeading.trueHeading > 0 ? newHeading.trueHeading : newHeading.magneticHeading)

Is also .. kinda okay, if I move and rotate. It is faulty, if I just rotate in place. Still cannot solve that one.
I also managed to make a custom followWithHeading, with this function:

func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {

        mapView.centerCoordinate = userLocationAnnotation.coordinate
            
        mapView.camera.heading = (newHeading.trueHeading > 0 ? newHeading.trueHeading : newHeading.magneticHeading)

        userLocationAnnotation.heading = -mapView.camera.heading + (newHeading.trueHeading > 0 ? newHeading.trueHeading : newHeading.magneticHeading)

    }

But the result is not as fluid as the original apple map rotation. If I rotate fast, then it is fine. But if I slowly turn my device, then the rotation is visibly not smooth.
See the result: https://imgur.com/a/SusV61a

相关问题