react-native-reanimated 3.13.0-rc.2 → 3.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Common/cpp/LayoutAnimations/LayoutAnimationsManager.cpp +8 -2
- package/Common/cpp/LayoutAnimations/LayoutAnimationsManager.h +3 -1
- package/Common/cpp/LayoutAnimations/LayoutAnimationsProxy.cpp +58 -33
- package/Common/cpp/LayoutAnimations/LayoutAnimationsProxy.h +19 -9
- package/Common/cpp/LayoutAnimations/LayoutAnimationsUtils.cpp +11 -7
- package/Common/cpp/LayoutAnimations/LayoutAnimationsUtils.h +14 -6
- package/Common/cpp/NativeModules/NativeReanimatedModule.cpp +1 -1
- package/Common/cpp/NativeModules/NativeReanimatedModule.h +1 -1
- package/Common/cpp/ReanimatedRuntime/WorkletRuntime.cpp +1 -1
- package/Common/cpp/ReanimatedRuntime/WorkletRuntime.h +1 -1
- package/Common/cpp/ReanimatedRuntime/WorkletRuntimeDecorator.cpp +6 -6
- package/Common/cpp/SharedItems/Shareables.cpp +25 -8
- package/Common/cpp/SharedItems/Shareables.h +12 -7
- package/android/CMakeLists.txt +1 -1
- package/android/src/main/cpp/LayoutAnimations.cpp +14 -0
- package/android/src/main/cpp/LayoutAnimations.h +5 -0
- package/android/src/main/cpp/NativeProxy.cpp +10 -0
- package/android/src/main/java/com/swmansion/reanimated/layoutReanimation/AnimationsManager.java +10 -2
- package/android/src/main/java/com/swmansion/reanimated/layoutReanimation/LayoutAnimations.java +2 -0
- package/android/src/main/java/com/swmansion/reanimated/layoutReanimation/NativeMethodsHolder.java +2 -0
- package/android/src/main/java/com/swmansion/reanimated/layoutReanimation/ReanimatedNativeHierarchyManager.java +10 -0
- package/android/src/main/java/com/swmansion/reanimated/layoutReanimation/ScreensHelper.java +83 -0
- package/android/src/main/java/com/swmansion/reanimated/layoutReanimation/SharedTransitionManager.java +130 -31
- package/android/src/main/java/com/swmansion/reanimated/layoutReanimation/Snapshot.java +36 -0
- package/android/src/main/java/com/swmansion/reanimated/layoutReanimation/TabNavigatorObserver.java +128 -0
- package/android/src/paper/java/com/swmansion/reanimated/NativeProxy.java +8 -0
- package/android/src/reactNativeVersionPatch/RuntimeExecutor/73/com/swmansion/reanimated/NativeProxy.java +6 -0
- package/android/src/reactNativeVersionPatch/RuntimeExecutor/latest/com/swmansion/reanimated/NativeProxy.java +6 -0
- package/apple/LayoutReanimation/REAAnimationsManager.h +2 -0
- package/apple/LayoutReanimation/REAAnimationsManager.m +5 -0
- package/apple/LayoutReanimation/REAScreensHelper.h +6 -0
- package/apple/LayoutReanimation/REAScreensHelper.m +92 -4
- package/apple/LayoutReanimation/REASharedTransitionManager.h +1 -0
- package/apple/LayoutReanimation/REASharedTransitionManager.m +254 -55
- package/apple/native/NativeProxy.mm +12 -0
- package/lib/module/Colors.js +5 -2
- package/lib/module/Colors.js.map +1 -1
- package/lib/module/UpdateProps.js +8 -8
- package/lib/module/UpdateProps.js.map +1 -1
- package/lib/module/ViewDescriptorsSet.js +0 -27
- package/lib/module/ViewDescriptorsSet.js.map +1 -1
- package/lib/module/createAnimatedComponent/InlinePropManager.js +1 -7
- package/lib/module/createAnimatedComponent/InlinePropManager.js.map +1 -1
- package/lib/module/createAnimatedComponent/PropsFilter.js +1 -6
- package/lib/module/createAnimatedComponent/PropsFilter.js.map +1 -1
- package/lib/module/createAnimatedComponent/commonTypes.js.map +1 -1
- package/lib/module/createAnimatedComponent/createAnimatedComponent.js +1 -5
- package/lib/module/createAnimatedComponent/createAnimatedComponent.js.map +1 -1
- package/lib/module/hook/commonTypes.js.map +1 -1
- package/lib/module/hook/useAnimatedStyle.js +12 -15
- package/lib/module/hook/useAnimatedStyle.js.map +1 -1
- package/lib/module/hook/useFrameCallback.js +2 -2
- package/lib/module/hook/useFrameCallback.js.map +1 -1
- package/lib/module/hook/useWorkletCallback.js +1 -1
- package/lib/module/hook/useWorkletCallback.js.map +1 -1
- package/lib/module/js-reanimated/index.js +3 -28
- package/lib/module/js-reanimated/index.js.map +1 -1
- package/lib/module/js-reanimated/webUtils.js +9 -0
- package/lib/module/js-reanimated/webUtils.js.map +1 -0
- package/lib/module/js-reanimated/webUtils.web.js +25 -0
- package/lib/module/js-reanimated/webUtils.web.js.map +1 -0
- package/lib/module/layoutReanimation/defaultTransitions/CurvedTransition.js +1 -0
- package/lib/module/layoutReanimation/defaultTransitions/CurvedTransition.js.map +1 -1
- package/lib/module/layoutReanimation/defaultTransitions/EntryExitTransition.js +1 -0
- package/lib/module/layoutReanimation/defaultTransitions/EntryExitTransition.js.map +1 -1
- package/lib/module/layoutReanimation/defaultTransitions/FadingTransition.js +11 -10
- package/lib/module/layoutReanimation/defaultTransitions/FadingTransition.js.map +1 -1
- package/lib/module/layoutReanimation/defaultTransitions/JumpingTransition.js +1 -0
- package/lib/module/layoutReanimation/defaultTransitions/JumpingTransition.js.map +1 -1
- package/lib/module/layoutReanimation/defaultTransitions/LinearTransition.js +1 -0
- package/lib/module/layoutReanimation/defaultTransitions/LinearTransition.js.map +1 -1
- package/lib/module/layoutReanimation/defaultTransitions/SequencedTransition.js +1 -0
- package/lib/module/layoutReanimation/defaultTransitions/SequencedTransition.js.map +1 -1
- package/lib/module/layoutReanimation/web/Easing.web.js +14 -0
- package/lib/module/layoutReanimation/web/Easing.web.js.map +1 -0
- package/lib/module/layoutReanimation/web/animationParser.js +16 -1
- package/lib/module/layoutReanimation/web/animationParser.js.map +1 -1
- package/lib/module/layoutReanimation/web/animationsManager.js +25 -8
- package/lib/module/layoutReanimation/web/animationsManager.js.map +1 -1
- package/lib/module/layoutReanimation/web/componentStyle.js +12 -16
- package/lib/module/layoutReanimation/web/componentStyle.js.map +1 -1
- package/lib/module/layoutReanimation/web/componentUtils.js +53 -18
- package/lib/module/layoutReanimation/web/componentUtils.js.map +1 -1
- package/lib/module/layoutReanimation/web/config.js +1 -12
- package/lib/module/layoutReanimation/web/config.js.map +1 -1
- package/lib/module/layoutReanimation/web/createAnimation.js +21 -2
- package/lib/module/layoutReanimation/web/createAnimation.js.map +1 -1
- package/lib/module/layoutReanimation/web/domUtils.js +6 -5
- package/lib/module/layoutReanimation/web/domUtils.js.map +1 -1
- package/lib/module/layoutReanimation/web/transition/Jumping.web.js +43 -0
- package/lib/module/layoutReanimation/web/transition/Jumping.web.js.map +1 -0
- package/lib/module/platform-specific/RNRenderer.web.js +1 -1
- package/lib/module/platform-specific/RNRenderer.web.js.map +1 -1
- package/lib/module/platform-specific/jsVersion.js +1 -1
- package/lib/module/platform-specific/jsVersion.js.map +1 -1
- package/lib/module/platformFunctions/setNativeProps.web.js +1 -3
- package/lib/module/platformFunctions/setNativeProps.web.js.map +1 -1
- package/lib/typescript/UpdateProps.d.ts +2 -3
- package/lib/typescript/ViewDescriptorsSet.d.ts +0 -9
- package/lib/typescript/createAnimatedComponent/commonTypes.d.ts +1 -2
- package/lib/typescript/hook/commonTypes.d.ts +3 -6
- package/lib/typescript/hook/useWorkletCallback.d.ts +1 -1
- package/lib/typescript/js-reanimated/index.d.ts +2 -4
- package/lib/typescript/js-reanimated/webUtils.d.ts +3 -0
- package/lib/typescript/js-reanimated/webUtils.web.d.ts +3 -0
- package/lib/typescript/layoutReanimation/defaultTransitions/CurvedTransition.d.ts +1 -0
- package/lib/typescript/layoutReanimation/defaultTransitions/EntryExitTransition.d.ts +1 -0
- package/lib/typescript/layoutReanimation/defaultTransitions/FadingTransition.d.ts +1 -0
- package/lib/typescript/layoutReanimation/defaultTransitions/JumpingTransition.d.ts +1 -0
- package/lib/typescript/layoutReanimation/defaultTransitions/LinearTransition.d.ts +1 -0
- package/lib/typescript/layoutReanimation/defaultTransitions/SequencedTransition.d.ts +1 -0
- package/lib/typescript/layoutReanimation/web/Easing.web.d.ts +10 -0
- package/lib/typescript/layoutReanimation/web/animationParser.d.ts +1 -2
- package/lib/typescript/layoutReanimation/web/componentStyle.d.ts +1 -1
- package/lib/typescript/layoutReanimation/web/componentUtils.d.ts +4 -3
- package/lib/typescript/layoutReanimation/web/config.d.ts +5 -12
- package/lib/typescript/layoutReanimation/web/createAnimation.d.ts +2 -0
- package/lib/typescript/layoutReanimation/web/domUtils.d.ts +1 -1
- package/lib/typescript/layoutReanimation/web/transition/Jumping.web.d.ts +29 -0
- package/lib/typescript/platform-specific/jsVersion.d.ts +1 -1
- package/package.json +4 -3
- package/src/Colors.ts +5 -2
- package/src/UpdateProps.ts +8 -11
- package/src/ViewDescriptorsSet.ts +0 -42
- package/src/createAnimatedComponent/InlinePropManager.ts +2 -8
- package/src/createAnimatedComponent/PropsFilter.tsx +0 -4
- package/src/createAnimatedComponent/commonTypes.ts +1 -2
- package/src/createAnimatedComponent/createAnimatedComponent.tsx +1 -5
- package/src/hook/commonTypes.ts +3 -6
- package/src/hook/useAnimatedStyle.ts +9 -26
- package/src/hook/useFrameCallback.ts +2 -2
- package/src/hook/useWorkletCallback.ts +1 -1
- package/src/js-reanimated/index.ts +11 -37
- package/src/js-reanimated/webUtils.ts +8 -0
- package/src/js-reanimated/webUtils.web.ts +27 -0
- package/src/layoutReanimation/defaultTransitions/CurvedTransition.ts +2 -0
- package/src/layoutReanimation/defaultTransitions/EntryExitTransition.ts +2 -0
- package/src/layoutReanimation/defaultTransitions/FadingTransition.ts +12 -10
- package/src/layoutReanimation/defaultTransitions/JumpingTransition.ts +2 -0
- package/src/layoutReanimation/defaultTransitions/LinearTransition.ts +2 -0
- package/src/layoutReanimation/defaultTransitions/SequencedTransition.ts +2 -0
- package/src/layoutReanimation/web/Easing.web.ts +15 -0
- package/src/layoutReanimation/web/animationParser.ts +30 -2
- package/src/layoutReanimation/web/animationsManager.ts +45 -12
- package/src/layoutReanimation/web/componentStyle.ts +13 -16
- package/src/layoutReanimation/web/componentUtils.ts +68 -25
- package/src/layoutReanimation/web/config.ts +5 -14
- package/src/layoutReanimation/web/createAnimation.ts +38 -4
- package/src/layoutReanimation/web/domUtils.ts +15 -5
- package/src/layoutReanimation/web/transition/Jumping.web.ts +44 -0
- package/src/platform-specific/RNRenderer.web.ts +1 -1
- package/src/platform-specific/jsVersion.ts +1 -1
- package/src/platformFunctions/setNativeProps.web.ts +1 -1
|
@@ -1,20 +1,28 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
AnimationConfig,
|
|
5
|
+
AnimationNames,
|
|
6
|
+
CustomConfig,
|
|
7
|
+
KeyframeDefinitions,
|
|
8
|
+
} from './config';
|
|
4
9
|
import { Animations } from './config';
|
|
5
10
|
import type {
|
|
6
11
|
AnimatedComponentProps,
|
|
7
12
|
LayoutAnimationStaticContext,
|
|
8
13
|
} from '../../createAnimatedComponent/commonTypes';
|
|
9
14
|
import { LayoutAnimationType } from '../animationBuilder/commonTypes';
|
|
15
|
+
import { createCustomKeyFrameAnimation } from './createAnimation';
|
|
10
16
|
import {
|
|
11
17
|
getProcessedConfig,
|
|
12
18
|
handleExitingAnimation,
|
|
13
19
|
handleLayoutTransition,
|
|
20
|
+
maybeModifyStyleForKeyframe,
|
|
14
21
|
setElementAnimation,
|
|
15
22
|
} from './componentUtils';
|
|
16
23
|
import { areDOMRectsEqual } from './domUtils';
|
|
17
24
|
import type { TransitionData } from './animationParser';
|
|
25
|
+
import { Keyframe } from '../animationBuilder';
|
|
18
26
|
import { makeElementVisible } from './componentStyle';
|
|
19
27
|
|
|
20
28
|
function chooseConfig<ComponentProps extends Record<string, unknown>>(
|
|
@@ -35,11 +43,11 @@ function chooseConfig<ComponentProps extends Record<string, unknown>>(
|
|
|
35
43
|
|
|
36
44
|
function checkUndefinedAnimationFail(
|
|
37
45
|
initialAnimationName: string,
|
|
38
|
-
|
|
46
|
+
needsCustomization: boolean
|
|
39
47
|
) {
|
|
40
48
|
// This prevents crashes if we try to set animations that are not defined.
|
|
41
|
-
// We don't care about layout transitions since they're created dynamically
|
|
42
|
-
if (initialAnimationName in Animations ||
|
|
49
|
+
// We don't care about layout transitions or custom keyframes since they're created dynamically
|
|
50
|
+
if (initialAnimationName in Animations || needsCustomization) {
|
|
43
51
|
return false;
|
|
44
52
|
}
|
|
45
53
|
|
|
@@ -86,7 +94,7 @@ function chooseAction(
|
|
|
86
94
|
) {
|
|
87
95
|
switch (animationType) {
|
|
88
96
|
case LayoutAnimationType.ENTERING:
|
|
89
|
-
setElementAnimation(element, animationConfig);
|
|
97
|
+
setElementAnimation(element, animationConfig, true);
|
|
90
98
|
break;
|
|
91
99
|
case LayoutAnimationType.LAYOUT:
|
|
92
100
|
transitionData.reversed = animationConfig.reversed;
|
|
@@ -111,25 +119,48 @@ function tryGetAnimationConfig<ComponentProps extends Record<string, unknown>>(
|
|
|
111
119
|
typeof config.constructor;
|
|
112
120
|
|
|
113
121
|
const isLayoutTransition = animationType === LayoutAnimationType.LAYOUT;
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
122
|
+
const isCustomKeyframe = config instanceof Keyframe;
|
|
123
|
+
|
|
124
|
+
let animationName;
|
|
125
|
+
|
|
126
|
+
if (isCustomKeyframe) {
|
|
127
|
+
animationName = createCustomKeyFrameAnimation(
|
|
128
|
+
(config as CustomConfig).definitions as KeyframeDefinitions
|
|
129
|
+
);
|
|
130
|
+
} else if (typeof config === 'function') {
|
|
131
|
+
animationName = config.presetName;
|
|
132
|
+
} else {
|
|
133
|
+
animationName = (config.constructor as ConstructorWithStaticContext)
|
|
134
|
+
.presetName;
|
|
135
|
+
}
|
|
118
136
|
|
|
119
137
|
const shouldFail = checkUndefinedAnimationFail(
|
|
120
138
|
animationName,
|
|
121
|
-
isLayoutTransition
|
|
139
|
+
isLayoutTransition || isCustomKeyframe
|
|
122
140
|
);
|
|
123
141
|
|
|
124
142
|
if (shouldFail) {
|
|
125
143
|
return null;
|
|
126
144
|
}
|
|
127
145
|
|
|
146
|
+
if (isCustomKeyframe) {
|
|
147
|
+
const keyframeTimestamps = Object.keys(
|
|
148
|
+
(config as CustomConfig).definitions as KeyframeDefinitions
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
if (
|
|
152
|
+
!(keyframeTimestamps.includes('100') || keyframeTimestamps.includes('to'))
|
|
153
|
+
) {
|
|
154
|
+
console.warn(
|
|
155
|
+
`[Reanimated] Neither '100' nor 'to' was specified in Keyframe definition. This may result in wrong final position of your component. One possible solution is to duplicate last timestamp in definition as '100' (or 'to')`
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
128
160
|
const animationConfig = getProcessedConfig(
|
|
129
161
|
animationName,
|
|
130
162
|
animationType,
|
|
131
|
-
config as CustomConfig
|
|
132
|
-
animationName as AnimationNames
|
|
163
|
+
config as CustomConfig
|
|
133
164
|
);
|
|
134
165
|
|
|
135
166
|
return animationConfig;
|
|
@@ -145,6 +176,8 @@ export function startWebLayoutAnimation<
|
|
|
145
176
|
) {
|
|
146
177
|
const animationConfig = tryGetAnimationConfig(props, animationType);
|
|
147
178
|
|
|
179
|
+
maybeModifyStyleForKeyframe(element, props.entering as CustomConfig);
|
|
180
|
+
|
|
148
181
|
if ((animationConfig?.animationName as AnimationNames) in Animations) {
|
|
149
182
|
maybeReportOverwrittenProperties(
|
|
150
183
|
Animations[animationConfig?.animationName as AnimationNames].style,
|
|
@@ -20,15 +20,12 @@ export const snapshots = new WeakMap<HTMLElement, ReanimatedSnapshot>();
|
|
|
20
20
|
|
|
21
21
|
export function makeElementVisible(element: HTMLElement, delay: number) {
|
|
22
22
|
if (delay === 0) {
|
|
23
|
-
_updatePropsJS(
|
|
24
|
-
{ visibility: 'initial' },
|
|
25
|
-
{ _component: element as ReanimatedHTMLElement }
|
|
26
|
-
);
|
|
23
|
+
_updatePropsJS({ visibility: 'initial' }, element as ReanimatedHTMLElement);
|
|
27
24
|
} else {
|
|
28
25
|
setTimeout(() => {
|
|
29
26
|
_updatePropsJS(
|
|
30
27
|
{ visibility: 'initial' },
|
|
31
|
-
|
|
28
|
+
element as ReanimatedHTMLElement
|
|
32
29
|
);
|
|
33
30
|
}, delay * 1000);
|
|
34
31
|
}
|
|
@@ -66,19 +63,19 @@ function fixElementPosition(
|
|
|
66
63
|
}
|
|
67
64
|
}
|
|
68
65
|
|
|
69
|
-
export function
|
|
70
|
-
|
|
66
|
+
export function setElementPosition(
|
|
67
|
+
element: HTMLElement,
|
|
71
68
|
snapshot: ReanimatedSnapshot
|
|
72
69
|
) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
70
|
+
element.style.transform = '';
|
|
71
|
+
element.style.position = 'absolute';
|
|
72
|
+
element.style.top = `${snapshot.top}px`;
|
|
73
|
+
element.style.left = `${snapshot.left}px`;
|
|
74
|
+
element.style.width = `${snapshot.width}px`;
|
|
75
|
+
element.style.height = `${snapshot.height}px`;
|
|
76
|
+
element.style.margin = '0px'; // tmpElement has absolute position, so margin is not necessary
|
|
80
77
|
|
|
81
|
-
if (
|
|
82
|
-
fixElementPosition(
|
|
78
|
+
if (element.parentElement) {
|
|
79
|
+
fixElementPosition(element, element.parentElement, snapshot);
|
|
83
80
|
}
|
|
84
81
|
}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
import { Animations, TransitionType
|
|
3
|
+
import { Animations, TransitionType } from './config';
|
|
4
4
|
import type {
|
|
5
5
|
AnimationCallback,
|
|
6
6
|
AnimationConfig,
|
|
7
7
|
AnimationNames,
|
|
8
8
|
CustomConfig,
|
|
9
|
-
|
|
9
|
+
KeyframeDefinitions,
|
|
10
10
|
} from './config';
|
|
11
|
+
import { WebEasings } from './Easing.web';
|
|
12
|
+
import type { WebEasingsNames } from './Easing.web';
|
|
11
13
|
import type { TransitionData } from './animationParser';
|
|
12
14
|
import { TransitionGenerator } from './createAnimation';
|
|
13
15
|
import { scheduleAnimationCleanup } from './domUtils';
|
|
@@ -17,7 +19,8 @@ import { ReduceMotion } from '../../commonTypes';
|
|
|
17
19
|
import { isReducedMotion } from '../../PlatformChecker';
|
|
18
20
|
import { LayoutAnimationType } from '../animationBuilder/commonTypes';
|
|
19
21
|
import type { ReanimatedSnapshot, ScrollOffsets } from './componentStyle';
|
|
20
|
-
import {
|
|
22
|
+
import { setElementPosition, snapshots } from './componentStyle';
|
|
23
|
+
import { Keyframe } from '../animationBuilder';
|
|
21
24
|
|
|
22
25
|
function getEasingFromConfig(config: CustomConfig): string {
|
|
23
26
|
const easingName =
|
|
@@ -63,12 +66,15 @@ export function getReducedMotionFromConfig(config: CustomConfig) {
|
|
|
63
66
|
|
|
64
67
|
function getDurationFromConfig(
|
|
65
68
|
config: CustomConfig,
|
|
66
|
-
|
|
67
|
-
animationName: AnimationNames
|
|
69
|
+
animationName: string
|
|
68
70
|
): number {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
// Duration in keyframe has to be in seconds. However, when using `.duration()` modifier we pass it in miliseconds.
|
|
72
|
+
// If `duration` was specified in config, we have to divide it by `1000`, otherwise we return value that is already in seconds.
|
|
73
|
+
|
|
74
|
+
const defaultDuration =
|
|
75
|
+
animationName in Animations
|
|
76
|
+
? Animations[animationName as AnimationNames].duration
|
|
77
|
+
: 0.3;
|
|
72
78
|
|
|
73
79
|
return config.durationV !== undefined
|
|
74
80
|
? config.durationV / 1000
|
|
@@ -86,17 +92,12 @@ function getReversedFromConfig(config: CustomConfig) {
|
|
|
86
92
|
export function getProcessedConfig(
|
|
87
93
|
animationName: string,
|
|
88
94
|
animationType: LayoutAnimationType,
|
|
89
|
-
config: CustomConfig
|
|
90
|
-
initialAnimationName: AnimationNames
|
|
95
|
+
config: CustomConfig
|
|
91
96
|
): AnimationConfig {
|
|
92
97
|
return {
|
|
93
98
|
animationName,
|
|
94
99
|
animationType,
|
|
95
|
-
duration: getDurationFromConfig(
|
|
96
|
-
config,
|
|
97
|
-
animationType === LayoutAnimationType.LAYOUT,
|
|
98
|
-
initialAnimationName
|
|
99
|
-
),
|
|
100
|
+
duration: getDurationFromConfig(config, animationName),
|
|
100
101
|
delay: getDelayFromConfig(config),
|
|
101
102
|
easing: getEasingFromConfig(config),
|
|
102
103
|
callback: getCallbackFromConfig(config),
|
|
@@ -104,6 +105,28 @@ export function getProcessedConfig(
|
|
|
104
105
|
};
|
|
105
106
|
}
|
|
106
107
|
|
|
108
|
+
export function maybeModifyStyleForKeyframe(
|
|
109
|
+
element: HTMLElement,
|
|
110
|
+
config: CustomConfig
|
|
111
|
+
) {
|
|
112
|
+
if (!(config instanceof Keyframe)) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// We need to set `animationFillMode` to `forwards`, otherwise component will go back to its position.
|
|
117
|
+
// This will result in wrong snapshot
|
|
118
|
+
element.style.animationFillMode = 'forwards';
|
|
119
|
+
|
|
120
|
+
for (const timestampRules of Object.values(
|
|
121
|
+
config.definitions as KeyframeDefinitions
|
|
122
|
+
)) {
|
|
123
|
+
if ('originX' in timestampRules || 'originY' in timestampRules) {
|
|
124
|
+
element.style.position = 'absolute';
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
107
130
|
export function saveSnapshot(element: HTMLElement) {
|
|
108
131
|
const rect = element.getBoundingClientRect();
|
|
109
132
|
|
|
@@ -120,16 +143,31 @@ export function saveSnapshot(element: HTMLElement) {
|
|
|
120
143
|
|
|
121
144
|
export function setElementAnimation(
|
|
122
145
|
element: HTMLElement,
|
|
123
|
-
animationConfig: AnimationConfig
|
|
146
|
+
animationConfig: AnimationConfig,
|
|
147
|
+
shouldSavePosition = false
|
|
124
148
|
) {
|
|
125
149
|
const { animationName, duration, delay, easing } = animationConfig;
|
|
126
150
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
151
|
+
const configureAnimation = () => {
|
|
152
|
+
element.style.animationName = animationName;
|
|
153
|
+
element.style.animationDuration = `${duration}s`;
|
|
154
|
+
element.style.animationDelay = `${delay}s`;
|
|
155
|
+
element.style.animationTimingFunction = easing;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
if (animationConfig.animationType === LayoutAnimationType.ENTERING) {
|
|
159
|
+
// On chrome sometimes entering animations flicker. This is most likely caused by animation being interrupted
|
|
160
|
+
// by already started tasks. To avoid flickering, we use `requestAnimationFrame`, which will run callback right before repaint.
|
|
161
|
+
requestAnimationFrame(configureAnimation);
|
|
162
|
+
} else {
|
|
163
|
+
configureAnimation();
|
|
164
|
+
}
|
|
131
165
|
|
|
132
166
|
element.onanimationend = () => {
|
|
167
|
+
if (shouldSavePosition) {
|
|
168
|
+
saveSnapshot(element);
|
|
169
|
+
}
|
|
170
|
+
|
|
133
171
|
animationConfig.callback?.(true);
|
|
134
172
|
element.removeEventListener('animationcancel', animationCancelHandler);
|
|
135
173
|
};
|
|
@@ -144,7 +182,7 @@ export function setElementAnimation(
|
|
|
144
182
|
if (animationConfig.animationType === LayoutAnimationType.ENTERING) {
|
|
145
183
|
_updatePropsJS(
|
|
146
184
|
{ visibility: 'initial' },
|
|
147
|
-
|
|
185
|
+
element as ReanimatedHTMLElement
|
|
148
186
|
);
|
|
149
187
|
}
|
|
150
188
|
|
|
@@ -152,7 +190,11 @@ export function setElementAnimation(
|
|
|
152
190
|
};
|
|
153
191
|
|
|
154
192
|
if (!(animationName in Animations)) {
|
|
155
|
-
scheduleAnimationCleanup(animationName, duration + delay)
|
|
193
|
+
scheduleAnimationCleanup(animationName, duration + delay, () => {
|
|
194
|
+
if (shouldSavePosition) {
|
|
195
|
+
setElementPosition(element, snapshots.get(element)!);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
156
198
|
}
|
|
157
199
|
}
|
|
158
200
|
|
|
@@ -175,6 +217,9 @@ export function handleLayoutTransition(
|
|
|
175
217
|
case 'FadingTransition':
|
|
176
218
|
animationType = TransitionType.FADING;
|
|
177
219
|
break;
|
|
220
|
+
case 'JumpingTransition':
|
|
221
|
+
animationType = TransitionType.JUMPING;
|
|
222
|
+
break;
|
|
178
223
|
default:
|
|
179
224
|
animationType = TransitionType.LINEAR;
|
|
180
225
|
break;
|
|
@@ -220,8 +265,6 @@ export function handleExitingAnimation(
|
|
|
220
265
|
dummy.reanimatedDummy = true;
|
|
221
266
|
|
|
222
267
|
element.style.animationName = '';
|
|
223
|
-
// We hide current element so only its copy with proper animation will be displayed
|
|
224
|
-
element.style.visibility = 'hidden';
|
|
225
268
|
|
|
226
269
|
// After cloning the element, we want to move all children from original element to its clone. This is because original element
|
|
227
270
|
// will be unmounted, therefore when this code executes in child component, parent will be either empty or removed soon.
|
|
@@ -260,7 +303,7 @@ export function handleExitingAnimation(
|
|
|
260
303
|
|
|
261
304
|
snapshots.set(dummy, snapshot);
|
|
262
305
|
|
|
263
|
-
|
|
306
|
+
setElementPosition(dummy, snapshot);
|
|
264
307
|
|
|
265
308
|
const originalOnAnimationEnd = dummy.onanimationend;
|
|
266
309
|
|
|
@@ -37,10 +37,12 @@ import {
|
|
|
37
37
|
} from './animation/Stretch.web';
|
|
38
38
|
import { ZoomIn, ZoomInData, ZoomOut, ZoomOutData } from './animation/Zoom.web';
|
|
39
39
|
|
|
40
|
-
import type { AnimationData } from './animationParser';
|
|
40
|
+
import type { AnimationData, AnimationStyle } from './animationParser';
|
|
41
41
|
|
|
42
42
|
export type AnimationCallback = ((finished: boolean) => void) | null;
|
|
43
43
|
|
|
44
|
+
export type KeyframeDefinitions = Record<number, AnimationStyle>;
|
|
45
|
+
|
|
44
46
|
export interface AnimationConfig {
|
|
45
47
|
animationName: string;
|
|
46
48
|
animationType: LayoutAnimationType;
|
|
@@ -59,12 +61,14 @@ export interface CustomConfig {
|
|
|
59
61
|
reduceMotionV?: ReduceMotion;
|
|
60
62
|
callbackV?: AnimationCallback;
|
|
61
63
|
reversed?: boolean;
|
|
64
|
+
definitions?: KeyframeDefinitions;
|
|
62
65
|
}
|
|
63
66
|
|
|
64
67
|
export enum TransitionType {
|
|
65
68
|
LINEAR,
|
|
66
69
|
SEQUENCED,
|
|
67
70
|
FADING,
|
|
71
|
+
JUMPING,
|
|
68
72
|
}
|
|
69
73
|
|
|
70
74
|
export const AnimationsData: Record<string, AnimationData> = {
|
|
@@ -111,18 +115,5 @@ export const Animations = {
|
|
|
111
115
|
...RollOut,
|
|
112
116
|
};
|
|
113
117
|
|
|
114
|
-
// Those are the easings that can be implemented using Bezier curves.
|
|
115
|
-
// Others should be done as CSS animations
|
|
116
|
-
export const WebEasings = {
|
|
117
|
-
linear: [0, 0, 1, 1],
|
|
118
|
-
ease: [0.42, 0, 1, 1],
|
|
119
|
-
quad: [0.11, 0, 0.5, 0],
|
|
120
|
-
cubic: [0.32, 0, 0.67, 0],
|
|
121
|
-
sin: [0.12, 0, 0.39, 0],
|
|
122
|
-
circle: [0.55, 0, 1, 0.45],
|
|
123
|
-
exp: [0.7, 0, 0.84, 0],
|
|
124
|
-
};
|
|
125
|
-
|
|
126
118
|
export type AnimationNames = keyof typeof Animations;
|
|
127
119
|
export type LayoutTransitionsNames = keyof typeof AnimationsData;
|
|
128
|
-
export type WebEasingsNames = keyof typeof WebEasings;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
import { TransitionType } from './config';
|
|
4
|
+
import type { KeyframeDefinitions } from './config';
|
|
4
5
|
import { convertAnimationObjectToKeyframes } from './animationParser';
|
|
5
6
|
import type {
|
|
7
|
+
AnimationData,
|
|
6
8
|
ReanimatedWebTransformProperties,
|
|
7
9
|
TransitionData,
|
|
8
10
|
} from './animationParser';
|
|
@@ -10,16 +12,17 @@ import type { TransformsStyle } from 'react-native';
|
|
|
10
12
|
import { LinearTransition } from './transition/Linear.web';
|
|
11
13
|
import { SequencedTransition } from './transition/Sequenced.web';
|
|
12
14
|
import { FadingTransition } from './transition/Fading.web';
|
|
15
|
+
import { JumpingTransition } from './transition/Jumping.web';
|
|
13
16
|
import { insertWebAnimation } from './domUtils';
|
|
14
17
|
|
|
18
|
+
type TransformType = NonNullable<TransformsStyle['transform']>;
|
|
19
|
+
|
|
15
20
|
// Translate values are passed as numbers. However, if `translate` property receives number, it will not automatically
|
|
16
21
|
// convert it to `px`. Therefore if we want to keep transform we have to add 'px' suffix to each of translate values
|
|
17
22
|
// that are present inside transform.
|
|
18
23
|
//
|
|
19
24
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
20
|
-
function addPxToTranslate(
|
|
21
|
-
transform: NonNullable<TransformsStyle['transform']>
|
|
22
|
-
) {
|
|
25
|
+
function addPxToTranslate(transform: TransformType) {
|
|
23
26
|
type RNTransformProp = (typeof transform)[number];
|
|
24
27
|
|
|
25
28
|
// @ts-ignore `existingTransform` cannot be string because in that case
|
|
@@ -27,7 +30,7 @@ function addPxToTranslate(
|
|
|
27
30
|
const newTransform = transform.map((transformProp: RNTransformProp) => {
|
|
28
31
|
const newTransformProp: ReanimatedWebTransformProperties = {};
|
|
29
32
|
for (const [key, value] of Object.entries(transformProp)) {
|
|
30
|
-
if (key.includes('translate')) {
|
|
33
|
+
if (key.includes('translate') && typeof value === 'number') {
|
|
31
34
|
// @ts-ignore After many trials we decided to ignore this error - it says that we cannot use 'key' to index this object.
|
|
32
35
|
// Sadly it doesn't go away after using cast `key as keyof TransformProperties`.
|
|
33
36
|
newTransformProp[key] = `${value}px`;
|
|
@@ -42,6 +45,30 @@ function addPxToTranslate(
|
|
|
42
45
|
return newTransform;
|
|
43
46
|
}
|
|
44
47
|
|
|
48
|
+
export function createCustomKeyFrameAnimation(
|
|
49
|
+
keyframeDefinitions: KeyframeDefinitions
|
|
50
|
+
) {
|
|
51
|
+
for (const value of Object.values(keyframeDefinitions)) {
|
|
52
|
+
if (value.transform) {
|
|
53
|
+
value.transform = addPxToTranslate(value.transform as TransformType);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const animationData: AnimationData = {
|
|
58
|
+
name: '',
|
|
59
|
+
style: keyframeDefinitions,
|
|
60
|
+
duration: -1,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
animationData.name = generateNextCustomKeyframeName();
|
|
64
|
+
|
|
65
|
+
const parsedKeyframe = convertAnimationObjectToKeyframes(animationData);
|
|
66
|
+
|
|
67
|
+
insertWebAnimation(animationData.name, parsedKeyframe);
|
|
68
|
+
|
|
69
|
+
return animationData.name;
|
|
70
|
+
}
|
|
71
|
+
|
|
45
72
|
let customKeyframeCounter = 0;
|
|
46
73
|
|
|
47
74
|
function generateNextCustomKeyframeName() {
|
|
@@ -81,6 +108,13 @@ export function TransitionGenerator(
|
|
|
81
108
|
transitionData
|
|
82
109
|
);
|
|
83
110
|
break;
|
|
111
|
+
|
|
112
|
+
case TransitionType.JUMPING:
|
|
113
|
+
transitionObject = JumpingTransition(
|
|
114
|
+
transitionKeyframeName,
|
|
115
|
+
transitionData
|
|
116
|
+
);
|
|
117
|
+
break;
|
|
84
118
|
}
|
|
85
119
|
|
|
86
120
|
const transitionKeyframe =
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import type { ReanimatedHTMLElement } from '../../js-reanimated';
|
|
4
4
|
import { isWindowAvailable } from '../../PlatformChecker';
|
|
5
|
-
import {
|
|
5
|
+
import { setElementPosition, snapshots } from './componentStyle';
|
|
6
6
|
import { Animations } from './config';
|
|
7
7
|
import type { AnimationNames } from './config';
|
|
8
8
|
|
|
@@ -85,7 +85,10 @@ export function insertWebAnimation(animationName: string, keyframe: string) {
|
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
function removeWebAnimation(
|
|
88
|
+
function removeWebAnimation(
|
|
89
|
+
animationName: string,
|
|
90
|
+
animationRemoveCallback: () => void
|
|
91
|
+
) {
|
|
89
92
|
// Without this check SSR crashes because document is undefined (NextExample on CI)
|
|
90
93
|
if (!isWindowAvailable()) {
|
|
91
94
|
return;
|
|
@@ -101,7 +104,10 @@ function removeWebAnimation(animationName: string) {
|
|
|
101
104
|
throw new Error('[Reanimated] Failed to obtain animation index.');
|
|
102
105
|
}
|
|
103
106
|
|
|
107
|
+
animationRemoveCallback();
|
|
108
|
+
|
|
104
109
|
styleTag.sheet?.deleteRule(currentAnimationIndex);
|
|
110
|
+
|
|
105
111
|
animationNameList.splice(currentAnimationIndex, 1);
|
|
106
112
|
animationNameToIndex.delete(animationName);
|
|
107
113
|
|
|
@@ -123,7 +129,8 @@ const minimumFrames = 10;
|
|
|
123
129
|
|
|
124
130
|
export function scheduleAnimationCleanup(
|
|
125
131
|
animationName: string,
|
|
126
|
-
animationDuration: number
|
|
132
|
+
animationDuration: number,
|
|
133
|
+
animationRemoveCallback: () => void
|
|
127
134
|
) {
|
|
128
135
|
// If duration is very short, we want to keep remove delay to at least 10 frames
|
|
129
136
|
// In our case it is exactly 160/1099 s, which is approximately 0.15s
|
|
@@ -132,7 +139,10 @@ export function scheduleAnimationCleanup(
|
|
|
132
139
|
animationDuration + frameDurationMs * minimumFrames
|
|
133
140
|
);
|
|
134
141
|
|
|
135
|
-
setTimeout(
|
|
142
|
+
setTimeout(
|
|
143
|
+
() => removeWebAnimation(animationName, animationRemoveCallback),
|
|
144
|
+
timeoutValue
|
|
145
|
+
);
|
|
136
146
|
}
|
|
137
147
|
|
|
138
148
|
function reattachElementToAncestor(child: ReanimatedHTMLElement, parent: Node) {
|
|
@@ -147,7 +157,7 @@ function reattachElementToAncestor(child: ReanimatedHTMLElement, parent: Node) {
|
|
|
147
157
|
child.removedAfterAnimation = true;
|
|
148
158
|
parent.appendChild(child);
|
|
149
159
|
|
|
150
|
-
|
|
160
|
+
setElementPosition(child, childSnapshot);
|
|
151
161
|
|
|
152
162
|
const originalOnAnimationEnd = child.onanimationend;
|
|
153
163
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
import type { TransitionData } from '../animationParser';
|
|
3
|
+
import { Easing } from '../../../Easing';
|
|
4
|
+
|
|
5
|
+
export function JumpingTransition(
|
|
6
|
+
name: string,
|
|
7
|
+
transitionData: TransitionData
|
|
8
|
+
) {
|
|
9
|
+
const { translateX, translateY, scaleX, scaleY } = transitionData;
|
|
10
|
+
|
|
11
|
+
const d = Math.max(Math.abs(translateX), Math.abs(translateY)) / 2;
|
|
12
|
+
const peakTranslateY = translateY <= 0 ? translateY - d : -translateY + d;
|
|
13
|
+
|
|
14
|
+
const jumpingTransition = {
|
|
15
|
+
name,
|
|
16
|
+
style: {
|
|
17
|
+
0: {
|
|
18
|
+
transform: [
|
|
19
|
+
{
|
|
20
|
+
translateX: `${translateX}px`,
|
|
21
|
+
translateY: `${translateY}px`,
|
|
22
|
+
scale: `${scaleX},${scaleY}`,
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
easing: Easing.exp,
|
|
26
|
+
},
|
|
27
|
+
50: {
|
|
28
|
+
transform: [
|
|
29
|
+
{
|
|
30
|
+
translateX: `${translateX / 2}px`,
|
|
31
|
+
translateY: `${peakTranslateY}px`,
|
|
32
|
+
scale: `${scaleX},${scaleY}`,
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
100: {
|
|
37
|
+
transform: [{ translateX: '0px', translateY: '0px', scale: '1,1' }],
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
duration: 300,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
return jumpingTransition;
|
|
44
|
+
}
|