Custom pitch animation broken after commit 4dfa7482a6c0626ffbbaa3452a5b50858131f7c2
Environment
- Xcode version:
- iOS version: 14.5
- Devices affected: iPhone
- Maps SDK Version: v10.3.0
Observed behavior and steps to reproduce
@macdrevx FYI:
Custom camera animator does not animate pitch anymore. It instantly switches between states no matter the configuration (duration, delay etc). However, other animations like zoom, center, and bearing seem to be unaffected. I have been able to narrow it down to the specific commit: https://github.com/mapbox/mapbox-maps-ios/commit/4dfa7482a6c0626ffbbaa3452a5b50858131f7c2. The feature works fine in the commit prior to this and is broken after this commit.
Custom camera animator should fluidly animate pitch from one level to another
Notes / preliminary analysis
Additional links and references
What details can you offer about the custom animator you're using? Can you provide…
- Initial camera state before starting the animation
- Animator config
I'm alternating between this state with these configs:
static let EagleEyeViewZoomLevel: CGFloat = 11
static let EagleEyeViewPitch: CGFloat = 0.1
and this state:
static let FirstPersonViewPitch: CGFloat = 80
static let FirstPersonViewBearing: CLLocationDirection = 0
static let FirstPersonViewZoomLevel: CGFloat = 15.5
But I've tested multiple states and it still occurs. Are you unable to reproduce it?
Are you using one of the makeAnimator APIs or ease(to:...)?
Using makeAnimator
let zoomAnimator = mapView.camera.makeAnimator(duration: 2.5, curve: .easeInOut) { (transition) in
transition.zoom.toValue = zoomLevel
transition.pitch.toValue = pitch
}
let centerAnimator = mapView.camera.makeAnimator(duration: mapView.cameraState.zoom < 8 ? 2 : 1, curve: .easeInOut) { (transition) in
transition.center.toValue = pointCoordinate
transition.bearing.toValue = bearing
zoomAnimator.startAnimation(afterDelay: 0.2)
}
centerAnimator.startAnimation()
Here's a demo based on the code you provided. I ran this with the latest commit on the main branch and was unable to reproduce the issue you described. Could you try it out? If you're able to modify it so that it demonstrates the issue, please share it back so we can debug further.
import UIKit
import MapboxMaps
final class ViewController: UIViewController {
var mapView: MapView!
var camera: CameraState! {
didSet {
animate(
withCenter: camera.center,
zoom: camera.zoom,
bearing: camera.bearing,
pitch: camera.pitch)
}
}
let eagleEye = CameraState(
center: CLLocationCoordinate2D(latitude: 45, longitude: -90),
padding: .zero,
zoom: 11,
bearing: 0,
pitch: 0.1)
let firstPerson = CameraState(
center: CLLocationCoordinate2D(latitude: 45.001, longitude: -90.001),
padding: .zero,
zoom: 15.5,
bearing: 45,
pitch: 80)
override func viewDidLoad() {
super.viewDidLoad()
mapView = MapView(frame: view.bounds)
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(mapView)
// initialize camera
camera = eagleEye
mapView.mapboxMap.onNext(.mapLoaded) { _ in
// start a repeating timer to toggle the state
Timer.scheduledTimer(
timeInterval: 5,
target: self,
selector: #selector(self.toggleState),
userInfo: nil,
repeats: true)
}
}
@objc func toggleState() {
if camera == eagleEye {
camera = firstPerson
} else {
camera = eagleEye
}
}
func animate(withCenter center: CLLocationCoordinate2D,
zoom: CGFloat,
bearing: CLLocationDirection,
pitch: CGFloat) {
let zoomAnimator = mapView.camera.makeAnimator(duration: 2.5, curve: .easeInOut) { (transition) in
transition.zoom.toValue = zoom
transition.pitch.toValue = pitch
}
let centerAnimator = mapView.camera.makeAnimator(duration: mapView.cameraState.zoom < 8 ? 2 : 1, curve: .easeInOut) { (transition) in
transition.center.toValue = center
transition.bearing.toValue = bearing
zoomAnimator.startAnimation(afterDelay: 0.2)
}
centerAnimator.startAnimation()
}
}