Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introducing Keyframe-like animation definition schema #2195

Merged
merged 16 commits into from
Jul 20, 2021

Conversation

jmysliv
Copy link
Member

@jmysliv jmysliv commented Jul 12, 2021

Description

To simplify the way how complex animations are defined, this PR introduces a keyframe like animation definition schema. It is inspired by the animation definition schema used in CSS and react-native-animatable. In the result user will be able to define animation using Keyframe:

const enteringAnimation = new Keyframe({
    0: {
      transform: [{ scale: 0.4 }, { rotate: '45deg' }],
    },
    30: {
      transform: [{ scale: 1.5 }, { rotate: '-90deg' }],
    },
    100: {
      transform: [{ scale: 1 }, { rotate: '0deg' }],
      easing: Easing.quad,
    },
  })

After creating Keyframe object the user can pass it as a prop to Animated.View component (i.ex. as entering animation).

Changes

  • Added Keyframe animation builder

Screenshots / GIFs

keyframeAnimation.mov

Test code and steps to reproduce

Checklist

  • Included code example that can be used to test this change
  • Updated TS types
  • Added TS types tests
  • Added unit / integration tests
  • Updated documentation
  • Ensured that CI passes

@jmysliv jmysliv self-assigned this Jul 12, 2021
@piaskowyk piaskowyk self-requested a review July 12, 2021 15:02
Copy link
Member

@piaskowyk piaskowyk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solid PR 🚀

Example/src/LayoutReanimation/KeyframeAnimation.tsx Outdated Show resolved Hide resolved
@jmysliv jmysliv marked this pull request as ready for review July 13, 2021 14:34
@jmysliv jmysliv requested review from piaskowyk and Szymon20000 July 13, 2021 14:34
Copy link
Member

@jakub-gonet jakub-gonet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't part of the 2.3.0-alpha.1 release so adding docs to that may be unnecessary.

docs/docs/api/LayoutAnimations/ExitAnimations.md Outdated Show resolved Hide resolved
docs/docs/api/LayoutAnimations/KeyframeAnimations.md Outdated Show resolved Hide resolved
docs/docs/api/LayoutAnimations/KeyframeAnimations.md Outdated Show resolved Hide resolved
docs/docs/api/LayoutAnimations/KeyframeAnimations.md Outdated Show resolved Hide resolved
docs/docs/api/LayoutAnimations/KeyframeAnimations.md Outdated Show resolved Hide resolved
@jmysliv jmysliv requested review from jakub-gonet and piaskowyk July 15, 2021 08:26
@jmysliv
Copy link
Member Author

jmysliv commented Jul 15, 2021

After consultation with @piaskowyk we've changed the approach a little bit. When a property is missing from the keyframe, instead of copying its value from the previous keyframe, we decided to increase the duration of the animation to the value in the next keyframe. So in such case:

const animation = new Keyframe({
  from: {
    originX: 50,
    transform: [{ rotate: '45deg' }],
  },
  30: {
    transform: [{ rotate: '-90deg' }],
  },
  100: {
    originX: 0,
    transform: [{ rotate: '0deg' }],
    easing: Easing.quad,
  },
});

Animation to originX: 0 will start from the beginning and not after 30% of the animation duration like in the previous approach.

\cc @jakub-gonet

@jakub-gonet
Copy link
Member

This looks like a better approach. If I understand it correctly, do you try to "fill the gaps" between two occurrences of the given property and interpolate it between two points?

What happens if we have code like this?

const animation = new Keyframe({
  0: {
    originX: 50,   // <- this property is being interpolated
    transform: [{ rotate: '45deg' }],
    easing: Easing.linear,
  },
  30: {
    transform: [{ rotate: '-90deg' }],
    easing: Easing.bezier,
  },
  100: {
    originX: 0,
    transform: [{ rotate: '0deg' }],
    easing: Easing.quad,
  },
});

that is if we have different easings between those points? Do every property follows the same easing and originX will be approaching 0 from 50 first linearly and from 30% of animation by bezier curve?

On a side note, I'm not sure about mixing from/to with numbers. We may treat it as an alias or a simplified syntax. I'm leaning towards the latter but alias gives more freedom in defining animations. What do you think?

@jmysliv
Copy link
Member Author

jmysliv commented Jul 16, 2021

@jakub-gonet

This looks like a better approach. If I understand it correctly, do you try to "fill the gaps" between two occurrences of the given property and interpolate it between two points?

Yes, exactly.

What happens if we have code like this?

const animation = new Keyframe({
  0: {
    originX: 50,   // <- this property is being interpolated
    transform: [{ rotate: '45deg' }],
    easing: Easing.linear,
  },
  30: {
    transform: [{ rotate: '-90deg' }],
    easing: Easing.bezier,
  },
  100: {
    originX: 0,
    transform: [{ rotate: '0deg' }],
    easing: Easing.quad,
  },
});

that is if we have different easings between those points? Do every property follows the same easing and originX will be approaching 0 from 50 first linearly and from 30% of animation by bezier curve?

No, currently property follows only this easing which is defined in the same point. So, because originX: 0 is defined with Easing.quad it will be approaching 0 from 50 with such easing.

On a side note, I'm not sure about mixing from/to with numbers. We may treat it as an alias or a simplified syntax. I'm leaning towards the latter but alias gives more freedom in defining animations. What do you think?

@piaskowyk what do you think?

@piaskowyk
Copy link
Member

New edge case:

const animation = new Keyframe({
  from: {
    transform: [{rotate: '45deg'}, {scaleX: 1}, {rotate: '0deg'}],
  },
  to: {
    transform: [{rotate: '-90deg'}, {scaleX: 0.2}, {rotate: '80deg'}],
  }
});

@jmysliv jmysliv merged commit 84558ff into master Jul 20, 2021
@jmysliv jmysliv deleted the @jmysliv/keyframes-animations branch July 20, 2021 06:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants