├── .gitignore ├── App.tsx ├── README.md ├── babel.config.js ├── package.json ├── src ├── Colors.ts └── examples │ ├── RadiusBackground │ └── index.tsx │ └── TabHeart │ └── index.tsx ├── tsconfig.json ├── webpack.config.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | project.xcworkspace 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | 33 | # node.js 34 | # 35 | node_modules/ 36 | npm-debug.log 37 | yarn-error.log 38 | 39 | # BUCK 40 | buck-out/ 41 | \.buckd/ 42 | *.keystore 43 | 44 | # fastlane 45 | # 46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 47 | # screenshots whenever they are needed. 48 | # For more information about the recommended setup visit: 49 | # https://docs.fastlane.tools/best-practices/source-control/ 50 | 51 | */fastlane/report.xml 52 | */fastlane/Preview.html 53 | */fastlane/screenshots 54 | 55 | # Bundle artifacts 56 | *.jsbundle 57 | 58 | # CocoaPods 59 | /ios/Pods/ 60 | 61 | # Expo 62 | .expo/* 63 | web-build/ -------------------------------------------------------------------------------- /App.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Pressable, StyleSheet, Text, View } from 'react-native'; 3 | import { NavigationContainer, useNavigation } from '@react-navigation/native'; 4 | import { createStackNavigator } from '@react-navigation/stack'; 5 | import { SafeAreaView } from 'react-native-safe-area-context'; 6 | import { ScrollView } from 'react-native-gesture-handler'; 7 | 8 | import Colors from './src/Colors'; 9 | 10 | import RadiusBackground from './src/examples/RadiusBackground'; 11 | import TabHeart from './src/examples/TabHeart'; 12 | 13 | const Stack = createStackNavigator(); 14 | 15 | function HomeScreen() { 16 | const navigation = useNavigation(); 17 | 18 | return ( 19 | 20 | 21 | navigation.navigate('RadiusBackground')} 23 | style={styles.screenContianer} 24 | > 25 | 26 | Radius background 27 | 28 | 29 | navigation.navigate('TabHeart')} 31 | style={styles.screenContianer} 32 | > 33 | 34 | TabHeart 35 | 36 | 37 | 38 | 39 | ); 40 | } 41 | 42 | export default function App() { 43 | return ( 44 | 45 | 46 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | ); 58 | } 59 | 60 | const styles = StyleSheet.create({ 61 | contianer: { 62 | flex: 1, 63 | backgroundColor: Colors.black, 64 | paddingHorizontal: 10, 65 | paddingTop: 10, 66 | }, 67 | screenContianer: { 68 | paddingVertical: 16, 69 | paddingHorizontal: 12, 70 | backgroundColor: Colors.white, 71 | borderRadius: 8, 72 | marginVertical: 10, 73 | }, 74 | screenTitle: { 75 | fontSize: 28, 76 | fontWeight: 'bold', 77 | color: '#17202A', 78 | }, 79 | }); 80 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Native Animation Examples 2 | 3 |

4 | 5 | 6 | Supports Expo iOS 7 | 8 | 9 | 10 | Supports Expo Android 11 | 12 | 13 | 14 | Supports Expo Android 15 | 16 |

17 | 18 | ## 🚀 How to use 19 | 20 | > `yarn install ` 21 | 22 | - If you want to run in ios device `yarn ios`. 23 | - If you want to run in android device `yarn android`. 24 | 25 | # Purpose 26 | 27 | ### This library purpose is to share a diferents examples of comon uses cases of animations some of the there more easy and other more complex 28 | 29 | - The examples use Reanimated in version 2 and Moti: 30 | - [Reanimated](https://docs.expo.io/versions/latest/sdk/reanimated) 31 | - [Moti](https://moti.fyi/) 32 | 33 | > 🧠 Feel free to open a PR to add more axamples 34 | 35 | # Examples 36 | 37 | [Radius background](https://github.com/rokkoo/react-native-animation-examples/blob/main/src/examples/RadiusBackground/index.tsx) 38 | 39 | ![Radius background](https://media.giphy.com/media/MG1bwxObgFk2PO064s/giphy.gif) 40 | 41 | [Tab Heart](https://github.com/rokkoo/react-native-animation-examples/tree/main/src/examples/TabHeart/index.tsx) 42 | 43 | ![Tab Heart](https://media.giphy.com/media/jJX3pidl7iLGeBEpoW/giphy.gif) 44 | 45 | ## 📝 Docs 46 | 47 | - [Expo Reanimated docs](https://docs.expo.io/versions/latest/sdk/reanimated) 48 | - [Moti docs](https://moti.fyi/) 49 | - [Reanimated docs](https://docs.swmansion.com/react-native-reanimated/docs/2.0.0-alpha.8/) 50 | 51 | # Persons 52 | 53 | - Follor creator of Moti [Fernando Rojo](https://twitter.com/FernandoTheRojo) for updates. 54 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | return { 4 | presets: ['babel-preset-expo'], 5 | plugins: ['react-native-reanimated/plugin'] 6 | }; 7 | }; 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": { 3 | "name": "Alfonso Lasa", 4 | "url": "https://twitter.com/alfonso_dev" 5 | }, 6 | "description": "A repository with some examples with Reanimated and Moti library", 7 | "version": "0.0.1", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/rokkoo/react-native-animation-examples" 11 | }, 12 | "license": "MIT", 13 | "dependencies": { 14 | "@react-native-community/masked-view": "0.1.10", 15 | "@react-navigation/native": "^5.9.3", 16 | "@react-navigation/stack": "^5.14.3", 17 | "expo": "~40.0.0", 18 | "framer-motion": "^3.3.0", 19 | "moti": "^0.4.1", 20 | "react": "16.13.1", 21 | "react-dom": "16.13.1", 22 | "react-native": "https://github.com/expo/react-native/archive/sdk-40.0.1.tar.gz", 23 | "react-native-gesture-handler": "~1.8.0", 24 | "react-native-reanimated": "2.0.0-rc.0", 25 | "react-native-safe-area-context": "3.1.9", 26 | "react-native-screens": "~2.15.2", 27 | "react-native-web": "~0.13.12" 28 | }, 29 | "devDependencies": { 30 | "@babel/core": "~7.9.0", 31 | "@expo/webpack-config": "^0.12.58", 32 | "@types/react": "~16.9.35", 33 | "@types/react-native": "~0.63.2", 34 | "typescript": "~4.0.0" 35 | }, 36 | "scripts": { 37 | "start": "expo start", 38 | "android": "expo start --android", 39 | "ios": "expo start --ios", 40 | "web": "expo start --web", 41 | "eject": "expo eject" 42 | }, 43 | "private": false 44 | } 45 | -------------------------------------------------------------------------------- /src/Colors.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | orange: 'rgb(255, 87, 51)', 3 | yellow: 'rgb(224, 255, 51)', 4 | green: 'rgb(119, 255, 51)', 5 | blue: 'rgb(51, 54, 255)', 6 | pink: 'rgb(233, 51, 255)', 7 | black: 'rgb(33, 47, 60)', 8 | white: 'rgb(247, 249, 249)', 9 | red: 'rgb(231, 76, 60)' 10 | } -------------------------------------------------------------------------------- /src/examples/RadiusBackground/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useReducer, useState } from 'react'; 2 | import { Pressable, StyleSheet } from 'react-native'; 3 | import { View, AnimatePresence, SafeAreaView } from 'moti'; 4 | 5 | import Colors from '../../Colors'; 6 | 7 | const AimatedBackground = ({ bg }) => { 8 | return ( 9 | 33 | ); 34 | }; 35 | 36 | export default function RadiousBackground() { 37 | const [selectedColor, setSelectedColor] = useState(Colors.orange); 38 | const [backgroundColor, setBackgroundColor] = useState(selectedColor); 39 | const [visible, toggle] = useReducer((s) => !s, true); 40 | 41 | const ColorView = ({ color }) => { 42 | return ( 43 | { 45 | setSelectedColor((prevColor) => { 46 | setBackgroundColor(prevColor); 47 | return color; 48 | }); 49 | 50 | if (visible) { 51 | setTimeout(() => { 52 | toggle(); 53 | }, 0); 54 | } 55 | 56 | toggle(); 57 | }} 58 | > 59 | 60 | 61 | ); 62 | }; 63 | 64 | return ( 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | {visible && } 76 | 77 | 78 | ); 79 | } 80 | 81 | const styles = StyleSheet.create({ 82 | container: { 83 | flex: 1, 84 | justifyContent: 'center', 85 | }, 86 | bg: { 87 | position: 'absolute', 88 | borderRadius: 50, 89 | right: 0, 90 | }, 91 | colorsContianer: { 92 | zIndex: 10, 93 | marginTop: 20, 94 | flexDirection: 'row', 95 | justifyContent: 'center', 96 | }, 97 | colorContainer: { 98 | width: 50, 99 | height: 50, 100 | borderRadius: 40, 101 | borderColor: 'white', 102 | borderWidth: 4, 103 | marginHorizontal: 8, 104 | }, 105 | }); 106 | -------------------------------------------------------------------------------- /src/examples/TabHeart/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useReducer } from 'react'; 2 | import { StyleSheet, Pressable, View } from 'react-native'; 3 | import { View as MotiView, AnimatePresence, Text as MotiText } from 'moti'; 4 | import { AntDesign } from '@expo/vector-icons'; 5 | 6 | import Colors from '../../Colors'; 7 | 8 | const TabHeart = () => { 9 | const [like, toggleLike] = useReducer((l) => !l, false); 10 | 11 | return ( 12 | 13 | 14 | 15 | 16 | 24 | 38 | 43 | 44 | 45 | 46 | 47 | 52 | {like ? 'Like' : 'Dislike'} 53 | 54 | ) 55 | 56 | 57 | 58 | 59 | ); 60 | }; 61 | 62 | const styles = StyleSheet.create({ 63 | container: { 64 | alignItems: 'center', 65 | justifyContent: 'center', 66 | backgroundColor: Colors.black, 67 | flex: 1, 68 | }, 69 | animationContianer: { 70 | backgroundColor: '#283747', 71 | flexDirection: 'row', 72 | justifyContent: 'center', 73 | alignItems: 'center', 74 | paddingVertical: 18, 75 | paddingHorizontal: 40, 76 | borderRadius: 30, 77 | }, 78 | text: { 79 | color: Colors.white, 80 | fontSize: 24, 81 | marginLeft: 14, 82 | }, 83 | }); 84 | 85 | export default TabHeart; 86 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react-native", 4 | "target": "esnext", 5 | "lib": [ 6 | "esnext" 7 | ], 8 | "allowJs": true, 9 | "skipLibCheck": true, 10 | "noEmit": true, 11 | "allowSyntheticDefaultImports": true, 12 | "resolveJsonModule": true, 13 | "esModuleInterop": true, 14 | "moduleResolution": "node" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const createExpoWebpackConfigAsync = require('@expo/webpack-config') 2 | 3 | module.exports = async function (env, argv) { 4 | const config = await createExpoWebpackConfigAsync( 5 | { 6 | ...env, 7 | babel: { dangerouslyAddModulePathsToTranspile: ['moti'] }, 8 | }, 9 | argv 10 | ) 11 | 12 | return config 13 | } --------------------------------------------------------------------------------