Skip to content

Commit

Permalink
chore: Separate animation from transition (#45)
Browse files Browse the repository at this point in the history
* Separate animation from transition

* Separate config creation from class implementation

* Add transitions registry to the manager, add null check

* Changes after rebase
  • Loading branch information
MatiPl01 committed Jan 21, 2025
1 parent 6ebe518 commit ea9239f
Show file tree
Hide file tree
Showing 14 changed files with 257 additions and 167 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
#include <reanimated/CSS/CSSKeyframeAnimation.h>
#include "CSSAnimation.h"
#include <reanimated/CSS/CSSAnimation.h>

namespace reanimated {

CSSKeyframeAnimation::CSSKeyframeAnimation(
CSSAnimation::CSSAnimation(
jsi::Runtime &rt,
ShadowNode::Shared shadowNode,
const CSSAnimationConfig &config)
: CSSAnimation(shadowNode),
styleInterpolator(AnimationStyleInterpolator(rt, config.keyframedStyle)),
: shadowNode(shadowNode),
styleInterpolator(AnimationStyleInterpolator(rt, config.keyframeStyle)),
progressProvider(AnimationProgressProvider(
config.animationDuration,
config.animationDelay,
Expand All @@ -16,13 +17,13 @@ CSSKeyframeAnimation::CSSKeyframeAnimation(
getEasingFunction(rt, config.animationTimingFunction))),
fillMode(getAnimationFillMode(config.animationFillMode)) {}

void CSSKeyframeAnimation::updateSettings(
void CSSAnimation::updateSettings(
jsi::Runtime &rt,
const jsi::Value &settings) {
const auto settingsObject = settings.asObject(rt);
}

void CSSKeyframeAnimation::start(time_t timestamp) {
void CSSAnimation::start(time_t timestamp) {
progressProvider.update(timestamp);

if (progressProvider.getState() == Finished) {
Expand All @@ -34,7 +35,7 @@ void CSSKeyframeAnimation::start(time_t timestamp) {
progressProvider.reset(timestamp);
}

void CSSKeyframeAnimation::finish(const bool revertChanges) {
void CSSAnimation::finish(const bool revertChanges) {
// Set state to finishing to add one more frame in which we will revert
// changes applied during the animation
if (revertChanges) {
Expand All @@ -44,7 +45,7 @@ void CSSKeyframeAnimation::finish(const bool revertChanges) {
}
}

jsi::Value CSSKeyframeAnimation::update(jsi::Runtime &rt, time_t timestamp) {
jsi::Value CSSAnimation::update(jsi::Runtime &rt, time_t timestamp) {
progressProvider.update(timestamp);

// Check if the animation has not started yet because of the delay
Expand Down Expand Up @@ -77,13 +78,13 @@ jsi::Value CSSKeyframeAnimation::update(jsi::Runtime &rt, time_t timestamp) {
return updatedStyle;
}

jsi::Value CSSKeyframeAnimation::reset(jsi::Runtime &rt) {
jsi::Value CSSAnimation::reset(jsi::Runtime &rt) {
// Reset all styles applied during the animation and restore the
// view style (progress can be any value because it is not used by reset)
return styleInterpolator.reset(createUpdateContext(rt, 0, false));
}

CSSAnimationDirection CSSKeyframeAnimation::getAnimationDirection(
CSSAnimationDirection CSSAnimation::getAnimationDirection(
const std::string &str) {
static const std::unordered_map<std::string, CSSAnimationDirection>
strToEnumMap = {
Expand All @@ -101,7 +102,7 @@ CSSAnimationDirection CSSKeyframeAnimation::getAnimationDirection(
}
}

CSSAnimationFillMode CSSKeyframeAnimation::getAnimationFillMode(
CSSAnimationFillMode CSSAnimation::getAnimationFillMode(
const std::string &str) {
static const std::unordered_map<std::string, CSSAnimationFillMode>
strToEnumMap = {
Expand All @@ -119,7 +120,7 @@ CSSAnimationFillMode CSSKeyframeAnimation::getAnimationFillMode(
}
}

InterpolationUpdateContext CSSKeyframeAnimation::createUpdateContext(
InterpolationUpdateContext CSSAnimation::createUpdateContext(
jsi::Runtime &rt,
double progress,
bool directionChanged) const {
Expand All @@ -131,15 +132,15 @@ InterpolationUpdateContext CSSKeyframeAnimation::createUpdateContext(
progressProvider.hasDirectionChanged()};
}

jsi::Value CSSKeyframeAnimation::maybeApplyBackwardsFillMode(jsi::Runtime &rt) {
jsi::Value CSSAnimation::maybeApplyBackwardsFillMode(jsi::Runtime &rt) {
if (fillMode == backwards || fillMode == both) {
// Return the style from the first animation keyframe
return styleInterpolator.update(createUpdateContext(rt, 0, false));
}
return jsi::Value::undefined();
}

jsi::Value CSSKeyframeAnimation::maybeApplyForwardsFillMode(jsi::Runtime &rt) {
jsi::Value CSSAnimation::maybeApplyForwardsFillMode(jsi::Runtime &rt) {
if (fillMode == forwards || fillMode == both) {
// Don't restore the style from the view style if the forwards fill mode is
// applied
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
#pragma once

#include <reanimated/CSS/configs/CSSAnimationConfig.h>
#include <reanimated/CSS/easing/EasingFunctions.h>
#include <reanimated/CSS/interpolation/Interpolator.h>
#include <reanimated/CSS/interpolation/AnimationStyleInterpolator.h>
#include <reanimated/CSS/progress/AnimationProgressProvider.h>

#include <chrono>

namespace reanimated {

enum CSSAnimationFillMode { none, forwards, backwards, both };

enum CSSAnimationState {
pending,
running,
Expand All @@ -22,32 +26,46 @@ enum CSSAnimationState {

class CSSAnimation {
public:
CSSAnimation(ShadowNode::Shared shadowNode) : shadowNode(shadowNode) {}
CSSAnimation(
jsi::Runtime &rt,
ShadowNode::Shared shadowNode,
const CSSAnimationConfig &config);

CSSAnimationState getState() const {
return state;
}

ShadowNode::Shared getShadowNode() const {
return shadowNode;
}

virtual void updateSettings(jsi::Runtime &rt, const jsi::Value &settings) = 0;

virtual void updateViewStyle(jsi::Runtime &rt, const jsi::Value &value) = 0;
void updateSettings(jsi::Runtime &rt, const jsi::Value &settings);
void updateViewStyle(jsi::Runtime &rt, const jsi::Value &value) {
styleInterpolator.setFallbackValue(rt, value);
}

virtual void start(time_t timestamp) = 0;
void start(time_t timestamp);
void finish(const bool revertChanges);
jsi::Value update(jsi::Runtime &rt, time_t timestamp);
jsi::Value reset(jsi::Runtime &rt);

virtual void finish(const bool revertChanges) = 0;
private:
const ShadowNode::Shared shadowNode;
const CSSAnimationFillMode fillMode;

virtual jsi::Value update(jsi::Runtime &rt, time_t timestamp) = 0;
CSSAnimationState state = CSSAnimationState::pending;
AnimationStyleInterpolator styleInterpolator;
AnimationProgressProvider progressProvider;

virtual jsi::Value reset(jsi::Runtime &rt) = 0;
static CSSAnimationDirection getAnimationDirection(const std::string &str);
static CSSAnimationFillMode getAnimationFillMode(const std::string &str);

protected:
const ShadowNode::Shared shadowNode;
InterpolationUpdateContext createUpdateContext(
jsi::Runtime &rt,
double progress,
bool directionChanged) const;

CSSAnimationState state = CSSAnimationState::pending;
jsi::Value maybeApplyBackwardsFillMode(jsi::Runtime &rt);
jsi::Value maybeApplyForwardsFillMode(jsi::Runtime &rt);
};

} // namespace reanimated
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ CSSTransition::CSSTransition(
jsi::Runtime &rt,
ShadowNode::Shared shadowNode,
const CSSTransitionConfig &config)
: CSSAnimation(shadowNode),
: shadowNode(shadowNode),
styleInterpolator(TransitionStyleInterpolator(
rt,
config.transitionProperty,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,47 +1,32 @@
#pragma once

#include <reanimated/CSS/CSSAnimation.h>
#include <reanimated/CSS/configs/CSSTransitionConfig.h>
#include <reanimated/CSS/easing/EasingFunctions.h>
#include <reanimated/CSS/interpolation/TransitionStyleInterpolator.h>

#include <vector>

using namespace facebook;
using namespace react;

namespace reanimated {

struct CSSTransitionConfig {
// TODO - maybe add support for separate
// transition property configs
jsi::Array transitionProperty;
double transitionDuration;
jsi::Value &transitionTimingFunction;
double transitionDelay;
};

class CSSTransition : public CSSAnimation { // TODO - implement
class CSSTransition { // TODO - implement
public:
CSSTransition(
jsi::Runtime &rt,
ShadowNode::Shared shadowNode,
const CSSTransitionConfig &config);

void updateSettings(jsi::Runtime &rt, const jsi::Value &settings) override;

void updateViewStyle(jsi::Runtime &rt, const jsi::Value &value) override {
void updateSettings(jsi::Runtime &rt, const jsi::Value &settings);
void updateViewStyle(jsi::Runtime &rt, const jsi::Value &value) {
styleInterpolator.updateViewStyle(rt, value);
}

void start(time_t timestamp) override;

void finish(const bool revertChanges) override;

jsi::Value update(jsi::Runtime &rt, time_t timestamp) override;

jsi::Value reset(jsi::Runtime &rt) override;
void start(time_t timestamp);
void finish(const bool revertChanges);
jsi::Value update(jsi::Runtime &rt, time_t timestamp);
jsi::Value reset(jsi::Runtime &rt);

private:
const ShadowNode::Shared shadowNode;
TransitionStyleInterpolator styleInterpolator;
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#pragma once

#include <jsi/jsi.h>
#include <string>

using namespace facebook;

namespace reanimated {

struct CSSAnimationConfig {
jsi::Object keyframeStyle;
double animationDuration;
jsi::Value animationTimingFunction;
double animationDelay;
double animationIterationCount;
std::string animationDirection;
std::string animationFillMode;
};

inline jsi::Object getAnimationKeyframeStyle(
jsi::Runtime &rt,
const jsi::Object &config) {
return config.getProperty(rt, "animationName").asObject(rt);
}

inline double getAnimationDuration(
jsi::Runtime &rt,
const jsi::Object &config) {
return config.getProperty(rt, "animationDuration").asNumber();
}

inline jsi::Value getAnimationTimingFunction(
jsi::Runtime &rt,
const jsi::Object &config) {
return config.getProperty(rt, "animationTimingFunction");
}

inline double getAnimationDelay(jsi::Runtime &rt, const jsi::Object &config) {
return config.getProperty(rt, "animationDelay").asNumber();
}

inline double getAnimationIterationCount(
jsi::Runtime &rt,
const jsi::Object &config) {
return config.getProperty(rt, "animationIterationCount").asNumber();
}

inline std::string getAnimationDirection(
jsi::Runtime &rt,
const jsi::Object &config) {
return config.getProperty(rt, "animationDirection").asString(rt).utf8(rt);
}

inline std::string getAnimationFillMode(
jsi::Runtime &rt,
const jsi::Object &config) {
return config.getProperty(rt, "animationFillMode").asString(rt).utf8(rt);
}

CSSAnimationConfig parseCSSAnimationConfig(
jsi::Runtime &rt,
const jsi::Value &config) {
const auto &configObj = config.asObject(rt);

return {
std::move(getAnimationKeyframeStyle(rt, configObj)),
getAnimationDuration(rt, configObj),
std::move(getAnimationTimingFunction(rt, configObj)),
getAnimationDelay(rt, configObj),
getAnimationIterationCount(rt, configObj),
getAnimationDirection(rt, configObj),
getAnimationFillMode(rt, configObj)};
}

} // namespace reanimated
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#pragma once

#include <jsi/jsi.h>
#include <string>

using namespace facebook;
namespace reanimated {

struct CSSTransitionConfig {
jsi::Array transitionProperty;
double transitionDuration;
jsi::Value transitionTimingFunction;
double transitionDelay;
};

inline jsi::Array getTransitionProperty(
jsi::Runtime &rt,
const jsi::Object &config) {
return config.getProperty(rt, "transitionProperty").asObject(rt).asArray(rt);
}

inline double getTransitionDuration(
jsi::Runtime &rt,
const jsi::Object &config) {
return config.getProperty(rt, "transitionDuration").asNumber();
}

inline jsi::Value getTransitionTimingFunction(
jsi::Runtime &rt,
const jsi::Object &config) {
return config.getProperty(rt, "transitionTimingFunction");
}

inline double getTransitionDelay(jsi::Runtime &rt, const jsi::Object &config) {
return config.getProperty(rt, "transitionDelay").asNumber();
}

CSSTransitionConfig parseCSSTransitionConfig(
jsi::Runtime &rt,
const jsi::Value &config) {
const auto &configObj = config.asObject(rt);

return CSSTransitionConfig{
getTransitionProperty(rt, configObj),
getTransitionDuration(rt, configObj),
getTransitionTimingFunction(rt, configObj),
getTransitionDelay(rt, configObj)};
}

} // namespace reanimated
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,9 @@ class ProgressProvider {
std::optional<double> getPrevious() const {
return previousProgress;
}

bool getStartTime() const {
return startTime;
}

ProgressState getState() const {
return state;
}
Expand Down
Loading

0 comments on commit ea9239f

Please sign in to comment.