๐ซ Custom transitions
๐ฉ๐ฝโHow the animations work under the hoodโ
Our library is dependent on the react-native-reanimated
(v2) which we use to animate the wrapper around the notification components.
To understand the ins and outs of animations, you can also take a look at the documentation for the aforementioned React Native Reanimated
Our animation system is designed to recognize two kinds of transitions:
- transition in
- transition out
and it is based on one animated value (shared value) that represents these transitions and animates itself from 0
to 1
.
Its range should be self-explanatory, 0
represents the beginning of the transition in animation, whereas 1
stands for the starting point for the transition out kind of animation.
When the notification is about to show up, the value is animated from 0
to 1
. When the notification is about to dissapear, it goes from 1
to 0
.
Every time a notification is about to be shown, the library renders the UI part wrapped with an <Animated.View />
and applies animated styles to it so it knows how it should animate.
The source of these styles comes from the animation config that is generated with AnimationBuilder
class or generateAnimationConfig
function and is used internally by the library to generate the animations. You can also use it yourself to create whatever transition you desiere.
Summarizing, there are 4 properties that can controll the transition. They all are handled by AnimationBuilder
or generateAnimationConfig
and go as follows:
animationConfigIn
- spring / timing configuration for transition in. REQUIREDanimationConfigOut
- spring / timing configuration for transition out. Not required, fallbacks toanimationConfigIn
when not providedtransitionInStyles
- a worklet function that takes in the animated progress value. It has to return the animated styles. For transition intransitionOutStyles
- same as above but for transition out. Not required, fallbacks to ^
The return type of this function (generateAnimationConfig
) is CustomAnimationConfig
which you can then use when changing the animation types in, e.g., createNotification
or notify
call.
Generating transition config with AnimationBuilder
โ
The AnimationBuilder
takes in a config object as a property with which you can define the animation.
Below code snippets should give an idea how it works:
Example 1
export const MoveDown = new AnimationBuilder({
animationConfigIn: {
type: 'timing',
config: {
duration: 400,
},
},
transitionInStyles: (progress) => {
'worklet'
const translateY = interpolate(progress.value, [0, 1], [-100, 0])
return {
opacity: progress.value,
transform: [{ translateY }],
}
},
transitionOutStyles: (progress) => {
'worklet'
const translateY = interpolate(progress.value, [0, 1], [100, 0])
return {
opacity: progress.value,
transform: [{ translateY }],
}
},
})
Example 2
export const RotateIn = generateAnimationConfig({
animationConfigIn: {
type: 'timing',
config: {
duration: 700,
easing: Easing.out(Easing.exp),
},
},
transitionInStyles: (progress) => {
'worklet'
const rotate = interpolate(progress.value, [0, 1], [-360, 0])
return {
transform: [{ rotate: `${rotate}deg` }, { scale: progress.value }],
opacity: progress.value,
}
},
})
Example 3
export const MoveDownRotateIn = MoveDown.add(RotateIn)
Generating transition config with generateAnimationConfig
โ
generateAnimation config is deprecated
. Please use Animation builder which allows your animations to be more customizable.
The generateAnimationConfig
takes in a config object as a property with which you can define the animation.
The code snippets below should give an idea how it works:
Example 1
export const Example1 = generateAnimationConfig({
animationConfigIn: {
type: 'timing',
config: {
duration: 400,
easing: Easing.inOut(Easing.sin),
},
},
transitionInStyles: (progress) => {
'worklet'
const scale = interpolate(progress.value, [0, 1], [0.8, 1])
const translateY = interpolate(progress.value, [0, 1], [-100, 0])
return {
opacity: progress.value,
transform: [{ scale }, { translateY }],
}
},
})
Example 2
export const Example2 = generateAnimationConfig({
animationConfigIn: {
type: 'timing',
config: {
duration: 300,
},
},
animationConfigOut: {
type: 'spring',
config: {
damping: 4,
mass: 0.8,
},
},
transitionInStyles: (progress) => {
'worklet'
const scale = interpolate(progress.value, [0, 1], [0.8, 1])
const translateY = interpolate(progress.value, [0, 1], [-100, 0])
return {
opacity: progress.value,
transform: [{ scale }, { translateY }],
}
},
transitionOutStyles: (progress) => {
'worklet'
const scale = interpolate(progress.value, [0, 1], [0.8, 1])
const translateY = interpolate(progress.value, [0, 1], [100, 0])
return {
opacity: progress.value,
transform: [{ scale }, { translateY }],
}
},
})
As you can see in the above examples, you have full control over the styles and animation configs for both kind of transitions - in and out.
animationConfigIn
and animationConfigOut
โ
The type ofย animationConfigIn
and animationConfigOut
:
{
type: "timing" | "spring",
config: WithSpringConfig | WithTimingConfig // -> Reanimated type declarations
}
transitionInStyles
and transitionOutStyles
โ
The type ofย transitionInStyles
and transitionOutStyles
is the
following function (must be a worklet
):
type TransistionStylesConfigFunction = (progress: SharedValue<number>) => AnimatedStylesType