Paras Gorasiya
Paras Gorasiya

Reputation: 1351

Move MGLPointAnnotation on Mapbox Maps like uber

I am integrating Mapbox iOS SDK into my app. Right now I am stuck at a point where I want to achieve car tracking feature like Uber app.

I used to have that feature with Google Maps SDK but I cant make it work with Mapbox SDK.

I am adding MGLPointAnnotation object to add it on map and want to move it from point A to point B with animation.

I am doing it using

UIView.animate(withDuration: TimeInterval(duration), animations: {
    // Update annotation coordinate to be the destination coordinate
    point.coordinate = newCoordinate
}, completion: nil)

But for MGLPointAnnotation I can't change its image because when there's a turn I want to rotate the image(Annotation).

If I use MGLAnnotationView object I can change the image but I cant change its coordinate because its readonly.

What should I do here to achieve that functionality?

Upvotes: 0

Views: 961

Answers (1)

Alexandr Kolesnik
Alexandr Kolesnik

Reputation: 2204

Several years ago I wrote smth similar, I used GoggleMaps, look through the code, maybe it will be helpful, I really don't remember what are all that numbers in angle counting

    extension Double {

    var degrees: Double {
        return self * 180.0 / Double.pi
    }

}


extension CLLocationCoordinate2D {

    func angleToPosition(position : CLLocationCoordinate2D) -> CLLocationDegrees {
        let bearingRadians = atan2(Double(position.latitude - latitude), Double(position.longitude - longitude))
        var bearingDegrees = bearingRadians.degrees
        //        print("\(bearingDegrees)")
        var roundDegrees = 360.0
        if bearingDegrees < 0 {
            if bearingDegrees > -90 {
                roundDegrees = 350
            }
            if bearingDegrees < -90 && bearingDegrees > -180 {
                roundDegrees = 370
            }
            bearingDegrees += roundDegrees
            return 360 - bearingDegrees
        }
        roundDegrees = bearingDegrees < 90 ? 350 : 360
        if bearingDegrees > 90 && bearingDegrees < 180 {
            roundDegrees = 370
        }
        UserDefaults.standard.set(bearingDegrees, forKey: "bearingDegrees")
        return roundDegrees - bearingDegrees
    }

    func duration(toDestination destination: CLLocationCoordinate2D, withSpeed speed : Double) -> Double {
        let distance = GMSGeometryDistance(self, destination)
        return distance / (speed * (1000 / 3600))
    }

}

And this is the func which do the rotation, you can use it as soon as you receive new coordinates, or call it in for loop if you have certain polyline

func animateCarDrive(info: [String: Any]) {
    let speed = info["speed"] as? Double ?? 40 // if your car's speed is changeable
    let position = info["position"] as? CLLocationCoordinate2D // new point position
    let duration = marker.position.duration(toDestination: position, withSpeed: speed)
    marker.rotation = marker.position.angleToPosition(position: position)
    CATransaction.begin()
    CATransaction.setAnimationDuration(duration)
    marker.position = position
    CATransaction.commit()
}

Upvotes: 0

Related Questions