mapbox-maps-ios icon indicating copy to clipboard operation
mapbox-maps-ios copied to clipboard

Custom pitch animation broken after commit 4dfa7482a6c0626ffbbaa3452a5b50858131f7c2

Open ibmeister opened this issue 4 years ago • 5 comments

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

ibmeister avatar Mar 02 '22 22:03 ibmeister

What details can you offer about the custom animator you're using? Can you provide…

  • Initial camera state before starting the animation
  • Animator config

macdrevx avatar Mar 03 '22 01:03 macdrevx

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?

ibmeister avatar Mar 03 '22 01:03 ibmeister

Are you using one of the makeAnimator APIs or ease(to:...)?

macdrevx avatar Mar 03 '22 02:03 macdrevx

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()

ibmeister avatar Mar 03 '22 02:03 ibmeister

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()
    }
}

macdrevx avatar Mar 03 '22 03:03 macdrevx