diff --git a/include/mbgl/map/camera.hpp b/include/mbgl/map/camera.hpp index a1b9bfe691a..cb2c7bdbf11 100644 --- a/include/mbgl/map/camera.hpp +++ b/include/mbgl/map/camera.hpp @@ -58,13 +58,14 @@ struct AnimationOptions { /** The easing timing curve of the transition. */ optional easing; - /** A function that is called on each frame of the transition, just before a - screen update, except on the last frame. The first parameter indicates - the elapsed time as a percentage of the duration. */ + /** A function that is called from the Map thread on each frame of the + transition, just before a screen update, except on the last frame. The + first parameter indicates the elapsed time as a percentage of the + duration. */ std::function transitionFrameFn; - /** A function that is called once on the last frame of the transition, just - before the corresponding screen update. */ + /** A function that is called once from the Map thread on the last frame of + the transition, just before the corresponding screen update. */ std::function transitionFinishFn; /** Creates an animation with no options specified. */ diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp index 6ec387ac23a..e4c8deac349 100644 --- a/src/mbgl/map/transform.cpp +++ b/src/mbgl/map/transform.cpp @@ -553,13 +553,11 @@ void Transform::startTransition(const CameraOptions& camera, const AnimationOptions& animation, std::function frame, const Duration& duration) { - if (transitionFinishFn) { + bool isAnimated = duration != Duration::zero(); + if (isAnimated && transitionFinishFn) { transitionFinishFn(); } - bool isAnimated = duration != Duration::zero(); - view.notifyMapChange(isAnimated ? MapChangeRegionWillChangeAnimated : MapChangeRegionWillChange); - // Associate the anchor, if given, with a coordinate. PrecisionPoint anchor = camera.anchor ? *camera.anchor : PrecisionPoint(NAN, NAN); LatLng anchorLatLng; @@ -567,12 +565,8 @@ void Transform::startTransition(const CameraOptions& camera, anchor.y = state.getHeight() - anchor.y; anchorLatLng = state.pointToLatLng(anchor); } - - transitionStart = Clock::now(); - transitionDuration = duration; - - transitionFrameFn = [isAnimated, animation, frame, anchor, anchorLatLng, this](const TimePoint now) { - float t = isAnimated ? (std::chrono::duration(now - transitionStart) / transitionDuration) : 1.0; + + auto frameFn = [animation, frame, anchor, anchorLatLng, this](double t) { Update result; if (t >= 1.0) { result = frame(1.0); @@ -584,6 +578,24 @@ void Transform::startTransition(const CameraOptions& camera, if (_validPoint(anchor)) { state.moveLatLng(anchorLatLng, anchor); } + return result; + }; + + if (!isAnimated) { + view.notifyMapChange(MapChangeRegionWillChange); + frameFn(1.0); + view.notifyMapChange(MapChangeRegionDidChange); + return; + } + + view.notifyMapChange(MapChangeRegionWillChangeAnimated); + + transitionStart = Clock::now(); + transitionDuration = duration; + + transitionFrameFn = [isAnimated, animation, frame, anchor, anchorLatLng, frameFn, this](const TimePoint now) { + float t = isAnimated ? (std::chrono::duration(now - transitionStart) / transitionDuration) : 1.0; + Update result = frameFn(t); // At t = 1.0, a DidChangeAnimated notification should be sent from finish(). if (t < 1.0) { @@ -611,10 +623,6 @@ void Transform::startTransition(const CameraOptions& camera, } view.notifyMapChange(isAnimated ? MapChangeRegionDidChangeAnimated : MapChangeRegionDidChange); }; - - if (!isAnimated) { - transitionFrameFn(Clock::now()); - } } bool Transform::inTransition() const {