1 | import * as React from 'react';
|
2 | import { Animated, StyleSheet, View } from 'react-native';
|
3 | import Icon, { isValidIcon, isEqualIcon } from './Icon';
|
4 | import { withTheme } from '../core/theming';
|
5 |
|
6 | const CrossFadeIcon = _ref => {
|
7 | let {
|
8 | color,
|
9 | size,
|
10 | source,
|
11 | theme
|
12 | } = _ref;
|
13 | const [currentIcon, setCurrentIcon] = React.useState(() => source);
|
14 | const [previousIcon, setPreviousIcon] = React.useState(null);
|
15 | const {
|
16 | current: fade
|
17 | } = React.useRef(new Animated.Value(1));
|
18 | const {
|
19 | scale
|
20 | } = theme.animation;
|
21 |
|
22 | if (currentIcon !== source) {
|
23 | setPreviousIcon(() => currentIcon);
|
24 | setCurrentIcon(() => source);
|
25 | }
|
26 |
|
27 | React.useEffect(() => {
|
28 | if (isValidIcon(previousIcon) && !isEqualIcon(previousIcon, currentIcon)) {
|
29 | fade.setValue(1);
|
30 | Animated.timing(fade, {
|
31 | duration: scale * 200,
|
32 | toValue: 0,
|
33 | useNativeDriver: true
|
34 | }).start();
|
35 | }
|
36 | }, [currentIcon, previousIcon, fade, scale]);
|
37 | const opacityPrev = fade;
|
38 | const opacityNext = previousIcon ? fade.interpolate({
|
39 | inputRange: [0, 1],
|
40 | outputRange: [1, 0]
|
41 | }) : 1;
|
42 | const rotatePrev = fade.interpolate({
|
43 | inputRange: [0, 1],
|
44 | outputRange: ['-90deg', '0deg']
|
45 | });
|
46 | const rotateNext = previousIcon ? fade.interpolate({
|
47 | inputRange: [0, 1],
|
48 | outputRange: ['0deg', '-180deg']
|
49 | }) : '0deg';
|
50 | return React.createElement(View, {
|
51 | style: [styles.content, {
|
52 | height: size,
|
53 | width: size
|
54 | }]
|
55 | }, previousIcon ? React.createElement(Animated.View, {
|
56 | style: [styles.icon, {
|
57 | opacity: opacityPrev,
|
58 | transform: [{
|
59 | rotate: rotatePrev
|
60 | }]
|
61 | }]
|
62 | }, React.createElement(Icon, {
|
63 | source: previousIcon,
|
64 | size: size,
|
65 | color: color
|
66 | })) : null, React.createElement(Animated.View, {
|
67 | style: [styles.icon, {
|
68 | opacity: opacityNext,
|
69 | transform: [{
|
70 | rotate: rotateNext
|
71 | }]
|
72 | }]
|
73 | }, React.createElement(Icon, {
|
74 | source: currentIcon,
|
75 | size: size,
|
76 | color: color
|
77 | })));
|
78 | };
|
79 |
|
80 | export default withTheme(CrossFadeIcon);
|
81 | const styles = StyleSheet.create({
|
82 | content: {
|
83 | alignItems: 'center',
|
84 | justifyContent: 'center'
|
85 | },
|
86 | icon: {
|
87 | position: 'absolute',
|
88 | top: 0,
|
89 | left: 0,
|
90 | right: 0,
|
91 | bottom: 0
|
92 | }
|
93 | });
|
94 |
|
\ | No newline at end of file |