Skip to content
This repository was archived by the owner on Nov 3, 2025. It is now read-only.

Commit 3c3d127

Browse files
committed
✨ (Transitions) add CardSkewUp
And clean other transitions.
1 parent fc74360 commit 3c3d127

6 files changed

Lines changed: 162 additions & 45 deletions

File tree

src/transitions/CardSkewUp.tsx

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import React, { Children } from 'react';
2+
import { StyleSheet, Dimensions } from 'react-native';
3+
import Animated, { Easing } from 'react-native-reanimated';
4+
5+
import { TransitionComponent } from './Transition';
6+
7+
const { height: SCREEN_HEIGHT } = Dimensions.get('window');
8+
9+
const {
10+
block,
11+
call,
12+
Clock,
13+
clockRunning,
14+
cond,
15+
multiply,
16+
set,
17+
startClock,
18+
stopClock,
19+
sub,
20+
timing,
21+
Value,
22+
} = Animated;
23+
24+
function runTiming(
25+
clock: Animated.Clock,
26+
value: Animated.Value<number>,
27+
dest: Animated.Value<number>,
28+
updateVisibility: () => any
29+
) {
30+
const state = {
31+
finished: new Value(0),
32+
frameTime: new Value(0),
33+
position: value,
34+
time: new Value(0),
35+
};
36+
37+
const config = {
38+
duration: 300,
39+
easing: Easing.inOut(Easing.ease),
40+
toValue: dest,
41+
};
42+
43+
return block([
44+
cond(
45+
clockRunning(clock),
46+
[
47+
// if the clock is already running we update the toValue, in case a new dest has been passed in
48+
set(config.toValue, dest),
49+
],
50+
[
51+
// If the clock isn't running we reset all the animation params and start the clock
52+
set(state.finished, 0),
53+
set(state.time, 0),
54+
set(state.position, value),
55+
set(state.frameTime, 0),
56+
set(config.toValue, dest),
57+
startClock(clock),
58+
]
59+
),
60+
// we run the step here that is going to update position
61+
timing(clock, state, config),
62+
// if the animation is over we stop the clock
63+
cond(state.finished, stopClock(clock)),
64+
cond(state.finished, [call([state.finished], updateVisibility), stopClock(clock)]),
65+
// we made the block return the updated position
66+
state.position,
67+
]);
68+
}
69+
70+
export class CardSkewUp extends TransitionComponent {
71+
state = {
72+
hidden: !this.props.directionForward,
73+
};
74+
75+
clock = new Clock();
76+
progress: Animated.Value<number> = new Value(this.props.directionForward ? 0 : 1);
77+
animation: Animated.Value<number> = new Value(this.props.directionForward ? 0 : 1);
78+
trans = runTiming(this.clock, this.progress, this.animation, () => {
79+
// react-native-reanimated is not correctly mocked
80+
// istanbul ignore next
81+
// @ts-ignore
82+
if (process.env.NODE_ENV !== 'test' && this.state.hidden !== !this.props.directionForward) {
83+
this.setState({ hidden: !this.props.directionForward });
84+
}
85+
});
86+
87+
componentDidUpdate() {
88+
this.animation.setValue(this.props.directionForward ? 0 : 1);
89+
if (this.state.hidden && this.props.directionForward) {
90+
this.setState({ hidden: false });
91+
}
92+
}
93+
94+
render() {
95+
return (
96+
<Animated.View
97+
pointerEvents={this.state.hidden ? 'none' : 'auto'}
98+
style={[
99+
StyleSheet.absoluteFill,
100+
{ backgroundColor: '#00000050', alignItems: 'center', justifyContent: 'center' },
101+
{ opacity: sub(new Value(1), this.trans) },
102+
]}
103+
>
104+
<Animated.View
105+
style={{
106+
transform: [
107+
{ perspective: 500 },
108+
{ rotateX: multiply(this.trans, -0.5) },
109+
{ translateY: multiply(this.trans, SCREEN_HEIGHT / 2) },
110+
],
111+
}}
112+
>
113+
{!this.state.hidden && Children.only(this.props.children)}
114+
</Animated.View>
115+
</Animated.View>
116+
);
117+
}
118+
}

src/transitions/RotateCrazy.tsx

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,29 @@
11
import React, { Children } from 'react';
2-
import { StyleSheet, Dimensions } from 'react-native';
2+
import { StyleSheet } from 'react-native';
33
import Animated, { Easing } from 'react-native-reanimated';
44

55
import { TransitionComponent } from './Transition';
66

7-
const { width: SCREEN_WIDTH } = Dimensions.get('window');
8-
97
const {
10-
sub,
11-
multiply,
8+
block,
9+
call,
1210
Clock,
13-
Value,
14-
set,
11+
clockRunning,
1512
cond,
13+
multiply,
14+
set,
1615
startClock,
17-
clockRunning,
18-
timing,
19-
and,
20-
eq,
2116
stopClock,
22-
block,
17+
sub,
18+
timing,
19+
Value,
2320
} = Animated;
2421

2522
function runTiming(
2623
clock: Animated.Clock,
2724
value: Animated.Value<number>,
2825
dest: Animated.Value<number>,
29-
setIsHidden: (value: boolean) => any
26+
updateVisibility: () => any
3027
) {
3128
const state = {
3229
finished: new Value(0),
@@ -62,7 +59,7 @@ function runTiming(
6259
timing(clock, state, config),
6360
// if the animation is over we stop the clock
6461
cond(state.finished, stopClock(clock)),
65-
cond(and(state.finished, eq(state.position, 1)), setIsHidden(true)),
62+
cond(state.finished, [call([state.finished], updateVisibility), stopClock(clock)]),
6663
// we made the block return the updated position
6764
state.position,
6865
]);
@@ -76,12 +73,12 @@ export class RotateCrazy extends TransitionComponent {
7673
clock = new Clock();
7774
progress: Animated.Value<number> = new Value(this.props.directionForward ? 0 : 1);
7875
animation: Animated.Value<number> = new Value(this.props.directionForward ? 0 : 1);
79-
trans = runTiming(this.clock, this.progress, this.animation, (hidden: boolean) => {
76+
trans = runTiming(this.clock, this.progress, this.animation, () => {
8077
// react-native-reanimated is not correctly mocked
8178
// istanbul ignore next
8279
// @ts-ignore
83-
if (process.env.NODE_ENV !== 'test' && this.state.hidden !== hidden) {
84-
this.setState({ hidden });
80+
if (process.env.NODE_ENV !== 'test' && this.state.hidden !== !this.props.directionForward) {
81+
this.setState({ hidden: !this.props.directionForward });
8582
}
8683
});
8784

@@ -95,14 +92,14 @@ export class RotateCrazy extends TransitionComponent {
9592
render() {
9693
return (
9794
<Animated.View
95+
pointerEvents={this.state.hidden ? 'none' : 'auto'}
9896
style={[
9997
StyleSheet.absoluteFill,
10098
{
10199
opacity: sub(new Value(1), this.trans),
102100
transform: [
103101
{
104102
rotate: multiply(this.trans, 5),
105-
translateX: multiply(this.trans, SCREEN_WIDTH),
106103
},
107104
],
108105
},

src/transitions/SlideLeft.tsx

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,24 @@ import { TransitionComponent } from './Transition';
77
const { width: SCREEN_WIDTH } = Dimensions.get('window');
88

99
const {
10-
multiply,
10+
block,
11+
call,
1112
Clock,
12-
Value,
13-
set,
13+
clockRunning,
1414
cond,
15+
multiply,
16+
set,
1517
startClock,
16-
clockRunning,
17-
timing,
18-
and,
19-
eq,
2018
stopClock,
21-
block,
19+
timing,
20+
Value,
2221
} = Animated;
2322

2423
function runTiming(
2524
clock: Animated.Clock,
2625
value: Animated.Value<number>,
2726
dest: Animated.Value<number>,
28-
setIsHidden: (value: boolean) => any
27+
updateVisibility: () => any
2928
) {
3029
const state = {
3130
finished: new Value(0),
@@ -60,8 +59,7 @@ function runTiming(
6059
// we run the step here that is going to update position
6160
timing(clock, state, config),
6261
// if the animation is over we stop the clock
63-
cond(state.finished, stopClock(clock)),
64-
cond(and(state.finished, eq(state.position, 1)), setIsHidden(true)),
62+
cond(state.finished, [call([state.finished], updateVisibility), stopClock(clock)]),
6563
// we made the block return the updated position
6664
state.position,
6765
]);
@@ -75,12 +73,12 @@ export class SlideLeft extends TransitionComponent {
7573
clock = new Clock();
7674
progress: Animated.Value<number> = new Value(this.props.directionForward ? 0 : 1);
7775
animation: Animated.Value<number> = new Value(this.props.directionForward ? 0 : 1);
78-
transX = runTiming(this.clock, this.progress, this.animation, (hidden: boolean) => {
76+
transX = runTiming(this.clock, this.progress, this.animation, () => {
7977
// react-native-reanimated is not correctly mocked
8078
// istanbul ignore next
8179
// @ts-ignore
82-
if (process.env.NODE_ENV !== 'test' && this.state.hidden !== hidden) {
83-
this.setState({ hidden });
80+
if (process.env.NODE_ENV !== 'test' && this.state.hidden !== !this.props.directionForward) {
81+
this.setState({ hidden: !this.props.directionForward });
8482
}
8583
});
8684

src/transitions/SlideUp.tsx

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,24 @@ import { TransitionComponent } from './Transition';
77
const { height: SCREEN_HEIGHT } = Dimensions.get('window');
88

99
const {
10-
multiply,
10+
block,
11+
call,
1112
Clock,
12-
Value,
13-
set,
13+
clockRunning,
1414
cond,
15+
multiply,
16+
set,
1517
startClock,
16-
clockRunning,
17-
timing,
18-
and,
19-
eq,
2018
stopClock,
21-
block,
19+
timing,
20+
Value,
2221
} = Animated;
2322

2423
function runTiming(
2524
clock: Animated.Clock,
2625
value: Animated.Value<number>,
2726
dest: Animated.Value<number>,
28-
setIsHidden: (value: boolean) => any
27+
updateVisibility: () => any
2928
) {
3029
const state = {
3130
finished: new Value(0),
@@ -61,7 +60,7 @@ function runTiming(
6160
timing(clock, state, config),
6261
// if the animation is over we stop the clock
6362
cond(state.finished, stopClock(clock)),
64-
cond(and(state.finished, eq(state.position, 1)), setIsHidden(true)),
63+
cond(state.finished, [call([state.finished], updateVisibility), stopClock(clock)]),
6564
// we made the block return the updated position
6665
state.position,
6766
]);
@@ -75,12 +74,12 @@ export class SlideUp extends TransitionComponent {
7574
clock = new Clock();
7675
progress: Animated.Value<number> = new Value(this.props.directionForward ? 0 : 1);
7776
animation: Animated.Value<number> = new Value(this.props.directionForward ? 0 : 1);
78-
transY = runTiming(this.clock, this.progress, this.animation, (hidden: boolean) => {
77+
transY = runTiming(this.clock, this.progress, this.animation, () => {
7978
// react-native-reanimated is not correctly mocked
8079
// istanbul ignore next
8180
// @ts-ignore
82-
if (process.env.NODE_ENV !== 'test' && this.state.hidden !== hidden) {
83-
this.setState({ hidden });
81+
if (process.env.NODE_ENV !== 'test' && this.state.hidden !== !this.props.directionForward) {
82+
this.setState({ hidden: !this.props.directionForward });
8483
}
8584
});
8685

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { describeTransitioner } from '../utils/describeTransitioner';
2+
import { CardSkewUp } from '../CardSkewUp';
3+
4+
describeTransitioner(CardSkewUp);

src/transitions/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export { None } from './None';
22
export { SlideLeft } from './SlideLeft';
33
export { SlideUp } from './SlideUp';
44
export { RotateCrazy } from './RotateCrazy';
5+
export { CardSkewUp } from './CardSkewUp';
56
export { TransitionComponent } from './Transition';
67

78
// test utility

0 commit comments

Comments
 (0)