Skip to content

Commit

Permalink
feat: add ripple effect tutorial
Browse files Browse the repository at this point in the history
  • Loading branch information
enzomanuelmangano committed Oct 16, 2021
1 parent a00b89b commit 3c6750f
Show file tree
Hide file tree
Showing 14 changed files with 6,174 additions and 0 deletions.
4 changes: 4 additions & 0 deletions 10-ripple-effect/.expo-shared/assets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true,
"40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true
}
13 changes: 13 additions & 0 deletions 10-ripple-effect/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
node_modules/
.expo/
npm-debug.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
*.orig.*
web-build/

# macOS
.DS_Store
41 changes: 41 additions & 0 deletions 10-ripple-effect/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Ripple from './components/Ripple';

export default function App() {
return (
<View style={styles.container}>
<Ripple
style={styles.ripple}
onTap={() => {
console.log('tap');
}}
>
<Text style={{ fontSize: 25 }}>Tap</Text>
</Ripple>
</View>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
ripple: {
width: 200,
height: 200,
backgroundColor: 'white',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 25,
// iOS
shadowOpacity: 0.2,
shadowOffset: { width: 0, height: 0 },
shadowRadius: 20,
// Android
elevation: 2,
},
});
32 changes: 32 additions & 0 deletions 10-ripple-effect/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"expo": {
"name": "10-ripple-effect",
"slug": "10-ripple-effect",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": [
"**/*"
],
"ios": {
"supportsTablet": true
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#FFFFFF"
}
},
"web": {
"favicon": "./assets/favicon.png"
}
}
}
Binary file added 10-ripple-effect/assets/adaptive-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 10-ripple-effect/assets/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 10-ripple-effect/assets/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 10-ripple-effect/assets/splash.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions 10-ripple-effect/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: ['react-native-reanimated/plugin'],
};
};
98 changes: 98 additions & 0 deletions 10-ripple-effect/components/Ripple.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import React from 'react';
import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native';
import {
TapGestureHandler,
TapGestureHandlerGestureEvent,
} from 'react-native-gesture-handler';
import Animated, {
measure,
runOnJS,
useAnimatedGestureHandler,
useAnimatedRef,
useAnimatedStyle,
useSharedValue,
withTiming,
} from 'react-native-reanimated';

interface RippleProps {
style?: StyleProp<ViewStyle>;
contentContainerStyle?: StyleProp<ViewStyle>;
onTap?: () => void;
}

const Ripple: React.FC<RippleProps> = ({
style,
onTap,
children,
contentContainerStyle,
}) => {
const centerX = useSharedValue(0);
const centerY = useSharedValue(0);
const scale = useSharedValue(0);

const aRef = useAnimatedRef<View>();
const width = useSharedValue(0);
const height = useSharedValue(0);

const rippleOpacity = useSharedValue(1);

const tapGestureEvent =
useAnimatedGestureHandler<TapGestureHandlerGestureEvent>({
onStart: (tapEvent) => {
const layout = measure(aRef);
width.value = layout.width;
height.value = layout.height;

centerX.value = tapEvent.x;
centerY.value = tapEvent.y;

rippleOpacity.value = 1;
scale.value = 0;
scale.value = withTiming(1, { duration: 1000 });
},
onActive: () => {
if (onTap) runOnJS(onTap)();
},
onFinish: () => {
rippleOpacity.value = withTiming(0);
},
});

const rStyle = useAnimatedStyle(() => {
const circleRadius = Math.sqrt(width.value ** 2 + height.value ** 2);

const translateX = centerX.value - circleRadius;
const translateY = centerY.value - circleRadius;

return {
width: circleRadius * 2,
height: circleRadius * 2,
borderRadius: circleRadius,
opacity: rippleOpacity.value,
backgroundColor: 'rgba(0,0,0,0.2)',
position: 'absolute',
top: 0,
left: 0,
transform: [
{ translateX },
{ translateY },
{
scale: scale.value,
},
],
};
});

return (
<View ref={aRef} style={style}>
<TapGestureHandler onGestureEvent={tapGestureEvent}>
<Animated.View style={[style, { overflow: 'hidden' }]}>
<View>{children}</View>
<Animated.View style={rStyle} />
</Animated.View>
</TapGestureHandler>
</View>
);
};

export default Ripple;
27 changes: 27 additions & 0 deletions 10-ripple-effect/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject"
},
"dependencies": {
"expo": "~42.0.1",
"expo-status-bar": "~1.0.4",
"react": "16.13.1",
"react-dom": "16.13.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-42.0.0.tar.gz",
"react-native-gesture-handler": "^1.10.3",
"react-native-reanimated": "^2.2.0",
"react-native-web": "~0.13.12"
},
"devDependencies": {
"@babel/core": "^7.9.0",
"@types/react": "~16.9.35",
"@types/react-native": "~0.63.2",
"typescript": "~4.0.0"
},
"private": true
}
6 changes: 6 additions & 0 deletions 10-ripple-effect/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true
}
}
Loading

0 comments on commit 3c6750f

Please sign in to comment.