From 8d2c1f6e7e964edc3fdda154af7db1b044d29aa1 Mon Sep 17 00:00:00 2001 From: Joshua Gross Date: Wed, 20 May 2020 19:40:00 -0700 Subject: [PATCH] LayoutImplementations: implement all existing animation curves besides Keyboard Summary: Implement EaseIn, EaseOut, EaseInOut, and Spring with SpringDamping. Note this does not yet implement Keyboard-type animation for iOS (coming soon), and the spring interpolator is VERY naive. We likely want to replace it with a "real" spring animation ASAP. The spring animation is identical to what Android does today, but would likely be a downgrade for iOS. I will do both in a followup. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D21675810 fbshipit-source-id: ac98554ebc81f0b81fdacefd6d848e3566e424c0 --- ReactCommon/fabric/animations/BUCK | 1 + .../LayoutAnimationKeyFrameManager.cpp | 53 ++++++++++++++++--- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/ReactCommon/fabric/animations/BUCK b/ReactCommon/fabric/animations/BUCK index fde3bc7decd..123fb6c45e2 100644 --- a/ReactCommon/fabric/animations/BUCK +++ b/ReactCommon/fabric/animations/BUCK @@ -36,6 +36,7 @@ rn_xplat_cxx_library( "-frtti", "-std=c++14", "-Wall", + "-lm", ], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), diff --git a/ReactCommon/fabric/animations/LayoutAnimationKeyFrameManager.cpp b/ReactCommon/fabric/animations/LayoutAnimationKeyFrameManager.cpp index 4f617bf71f5..034d871388b 100644 --- a/ReactCommon/fabric/animations/LayoutAnimationKeyFrameManager.cpp +++ b/ReactCommon/fabric/animations/LayoutAnimationKeyFrameManager.cpp @@ -105,7 +105,7 @@ static better::optional parseAnimationConfig( double duration = defaultDuration; double delay = 0; - double springDamping = 0; + double springDamping = 0.5; double initialVelocity = 0; auto const durationIt = config.find("duration"); @@ -236,13 +236,50 @@ LayoutAnimationKeyFrameManager::calculateAnimationProgress( uint64_t startTime = animation.startTime; uint64_t delay = mutationConfig.delay; uint64_t endTime = startTime + delay + mutationConfig.duration; - double progress = (now >= endTime) - ? 1 - : ((now < startTime + delay) ? 0 - : 1 - - (double)(endTime - delay - now) / - (double)(endTime - animation.startTime)); - return {progress, progress}; + + static const float PI = 3.14159265358979323846; + + if (now >= endTime) { + return {1, 1}; + } + if (now < startTime + delay) { + return {0, 0}; + } + + double linearTimeProgression = 1 - + (double)(endTime - delay - now) / (double)(endTime - animation.startTime); + + if (mutationConfig.animationType == AnimationType::Linear) { + return {linearTimeProgression, linearTimeProgression}; + } else if (mutationConfig.animationType == AnimationType::EaseIn) { + // This is an accelerator-style interpolator. + // In the future, this parameter (2.0) could be adjusted. This has been the + // default for Classic RN forever. + return {linearTimeProgression, pow(linearTimeProgression, 2.0)}; + } else if (mutationConfig.animationType == AnimationType::EaseOut) { + // This is an decelerator-style interpolator. + // In the future, this parameter (2.0) could be adjusted. This has been the + // default for Classic RN forever. + return {linearTimeProgression, 1.0 - pow(1 - linearTimeProgression, 2.0)}; + } else if (mutationConfig.animationType == AnimationType::EaseInEaseOut) { + // This is a combination of accelerate+decelerate. + // The animation starts and ends slowly, and speeds up in the middle. + return {linearTimeProgression, + cos((linearTimeProgression + 1.0) * PI) / 2 + 0.5}; + } else if (mutationConfig.animationType == AnimationType::Spring) { + // Using mSpringDamping in this equation is not really the exact + // mathematical springDamping, but a good approximation We need to replace + // this equation with the right Factor that accounts for damping and + // friction + double damping = mutationConfig.springDamping; + return { + linearTimeProgression, + (1 + + pow(2, -10 * linearTimeProgression) * + sin((linearTimeProgression - damping / 4) * PI * 2 / damping))}; + } else { + return {linearTimeProgression, linearTimeProgression}; + } } void LayoutAnimationKeyFrameManager::adjustDelayedMutationIndicesForMutation(