├── assets
├── images
│ ├── icon.png
│ ├── favicon.png
│ ├── splash.png
│ ├── react-logo.png
│ ├── adaptive-icon.png
│ ├── react-logo@2x.png
│ ├── react-logo@3x.png
│ └── partial-react-logo.png
└── fonts
│ └── SpaceMono-Regular.ttf
├── babel.config.js
├── .idea
├── .gitignore
├── vcs.xml
├── modules.xml
├── material_theme_project_new.xml
├── gradient-blur.iml
└── git_toolbox_prj.xml
├── app
├── _layout.tsx
└── index.tsx
├── tsconfig.json
├── .gitignore
├── app.json
├── README.md
├── package.json
└── scripts
└── reset-project.js
/assets/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bricezele/React-Native-Gradient-Blur/HEAD/assets/images/icon.png
--------------------------------------------------------------------------------
/assets/images/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bricezele/React-Native-Gradient-Blur/HEAD/assets/images/favicon.png
--------------------------------------------------------------------------------
/assets/images/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bricezele/React-Native-Gradient-Blur/HEAD/assets/images/splash.png
--------------------------------------------------------------------------------
/assets/images/react-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bricezele/React-Native-Gradient-Blur/HEAD/assets/images/react-logo.png
--------------------------------------------------------------------------------
/assets/images/adaptive-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bricezele/React-Native-Gradient-Blur/HEAD/assets/images/adaptive-icon.png
--------------------------------------------------------------------------------
/assets/images/react-logo@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bricezele/React-Native-Gradient-Blur/HEAD/assets/images/react-logo@2x.png
--------------------------------------------------------------------------------
/assets/images/react-logo@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bricezele/React-Native-Gradient-Blur/HEAD/assets/images/react-logo@3x.png
--------------------------------------------------------------------------------
/assets/fonts/SpaceMono-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bricezele/React-Native-Gradient-Blur/HEAD/assets/fonts/SpaceMono-Regular.ttf
--------------------------------------------------------------------------------
/assets/images/partial-react-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bricezele/React-Native-Gradient-Blur/HEAD/assets/images/partial-react-logo.png
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function (api) {
2 | api.cache(true);
3 | return {
4 | presets: ['babel-preset-expo'],
5 | };
6 | };
7 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # CodeStream ignored files
7 | /codestream.xml
8 |
--------------------------------------------------------------------------------
/app/_layout.tsx:
--------------------------------------------------------------------------------
1 | import { Stack } from "expo-router";
2 | import Index from "@/app/index";
3 |
4 | export default function RootLayout() {
5 | return (
6 |
7 | );
8 | }
9 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "expo/tsconfig.base",
3 | "compilerOptions": {
4 | "strict": true,
5 | "paths": {
6 | "@/*": [
7 | "./*"
8 | ]
9 | }
10 | },
11 | "include": [
12 | "**/*.ts",
13 | "**/*.tsx",
14 | ".expo/types/**/*.ts",
15 | "expo-env.d.ts"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .expo/
3 | dist/
4 | npm-debug.*
5 | *.jks
6 | *.p8
7 | *.p12
8 | *.key
9 | *.mobileprovision
10 | *.orig.*
11 | web-build/
12 |
13 | # macOS
14 | .DS_Store
15 |
16 | # @generated expo-cli sync-2b81b286409207a5da26e14c78851eb30d8ccbdb
17 | # The following patterns were generated by expo-cli
18 |
19 | expo-env.d.ts
20 | # @end expo-cli
--------------------------------------------------------------------------------
/.idea/material_theme_project_new.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/gradient-blur.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/git_toolbox_prj.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "expo": {
3 | "name": "gradient-blur",
4 | "slug": "gradient-blur",
5 | "version": "1.0.0",
6 | "orientation": "portrait",
7 | "icon": "./assets/images/icon.png",
8 | "scheme": "myapp",
9 | "userInterfaceStyle": "automatic",
10 | "splash": {
11 | "image": "./assets/images/splash.png",
12 | "resizeMode": "contain",
13 | "backgroundColor": "#ffffff"
14 | },
15 | "ios": {
16 | "supportsTablet": true
17 | },
18 | "android": {
19 | "adaptiveIcon": {
20 | "foregroundImage": "./assets/images/adaptive-icon.png",
21 | "backgroundColor": "#ffffff"
22 | }
23 | },
24 | "web": {
25 | "bundler": "metro",
26 | "output": "static",
27 | "favicon": "./assets/images/favicon.png"
28 | },
29 | "plugins": [
30 | "expo-router"
31 | ],
32 | "experiments": {
33 | "typedRoutes": true
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Native Gradient Blur 👋
2 |
3 | This is an [Expo](https://expo.dev) project created with [`create-expo-app`](https://www.npmjs.com/package/create-expo-app).
4 |
5 | # Gradient Blur Project
6 |
7 | This project demonstrates how to create a gradient blur effect using React Native and several libraries, including `@react-native-masked-view/masked-view`, `expo-linear-gradient`, `react-native-easing-gradient`, and `expo-blur`.
8 |
9 | ## Prerequisites
10 |
11 | Before you start, make sure you have the necessary libraries installed. You can install them using the following commands:
12 |
13 | ```sh
14 | npx expo install @react-native-masked-view/masked-view expo-linear-gradient expo-blur react-native-easing-gradient
15 | ```
16 |
17 | ## Demo
18 |
19 | https://github.com/bricezele/React-Native-Gradient-Blur/assets/14944418/52337a7b-1d78-44e4-9c55-12b1f0bf7516
20 |
21 |
22 | ## Join me
23 |
24 | - [Twitter](https://x.com/BriceZele)
25 | - [Linkedin](https://www.linkedin.com/in/brice-zele/): Chat with Expo users and ask questions.
26 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gradient-blur",
3 | "main": "expo-router/entry",
4 | "version": "1.0.0",
5 | "scripts": {
6 | "start": "expo start",
7 | "reset-project": "node ./scripts/reset-project.js",
8 | "android": "expo start --android",
9 | "ios": "expo start --ios",
10 | "web": "expo start --web",
11 | "test": "jest --watchAll",
12 | "lint": "expo lint"
13 | },
14 | "jest": {
15 | "preset": "jest-expo"
16 | },
17 | "dependencies": {
18 | "@expo/vector-icons": "^14.0.0",
19 | "@react-navigation/native": "^6.0.2",
20 | "expo": "~51.0.14",
21 | "expo-blur": "~13.0.2",
22 | "expo-constants": "~16.0.2",
23 | "expo-font": "~12.0.7",
24 | "expo-linear-gradient": "~13.0.2",
25 | "expo-linking": "~6.3.1",
26 | "expo-router": "~3.5.16",
27 | "expo-splash-screen": "~0.27.5",
28 | "expo-status-bar": "~1.12.1",
29 | "expo-system-ui": "~3.0.6",
30 | "expo-web-browser": "~13.0.3",
31 | "react": "18.2.0",
32 | "react-dom": "18.2.0",
33 | "react-native": "0.74.2",
34 | "react-native-easing-gradient": "^1.1.1",
35 | "react-native-gesture-handler": "~2.16.1",
36 | "react-native-reanimated": "~3.10.1",
37 | "react-native-safe-area-context": "4.10.1",
38 | "react-native-screens": "3.31.1",
39 | "react-native-web": "~0.19.10",
40 | "@react-native-masked-view/masked-view": "0.3.1"
41 | },
42 | "devDependencies": {
43 | "@babel/core": "^7.20.0",
44 | "@types/jest": "^29.5.12",
45 | "@types/react": "~18.2.45",
46 | "@types/react-test-renderer": "^18.0.7",
47 | "jest": "^29.2.1",
48 | "jest-expo": "~51.0.1",
49 | "react-test-renderer": "18.2.0",
50 | "typescript": "~5.3.3"
51 | },
52 | "private": true
53 | }
54 |
--------------------------------------------------------------------------------
/scripts/reset-project.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | /**
4 | * This script is used to reset the project to a blank state.
5 | * It moves the /app directory to /app-example and creates a new /app directory with an index.tsx and _layout.tsx file.
6 | * You can remove the `reset-project` script from package.json and safely delete this file after running it.
7 | */
8 |
9 | const fs = require('fs');
10 | const path = require('path');
11 |
12 | const root = process.cwd();
13 | const oldDirPath = path.join(root, 'app');
14 | const newDirPath = path.join(root, 'app-example');
15 | const newAppDirPath = path.join(root, 'app');
16 |
17 | const indexContent = `import { Text, View } from "react-native";
18 |
19 | export default function Index() {
20 | return (
21 |
28 | Edit app/index.tsx to edit this screen.
29 |
30 | );
31 | }
32 | `;
33 |
34 | const layoutContent = `import { Stack } from "expo-router";
35 |
36 | export default function RootLayout() {
37 | return (
38 |
39 |
40 |
41 | );
42 | }
43 | `;
44 |
45 | fs.rename(oldDirPath, newDirPath, (error) => {
46 | if (error) {
47 | return console.error(`Error renaming directory: ${error}`);
48 | }
49 | console.log('/app moved to /app-example.');
50 |
51 | fs.mkdir(newAppDirPath, { recursive: true }, (error) => {
52 | if (error) {
53 | return console.error(`Error creating new app directory: ${error}`);
54 | }
55 | console.log('New /app directory created.');
56 |
57 | const indexPath = path.join(newAppDirPath, 'index.tsx');
58 | fs.writeFile(indexPath, indexContent, (error) => {
59 | if (error) {
60 | return console.error(`Error creating index.tsx: ${error}`);
61 | }
62 | console.log('app/index.tsx created.');
63 |
64 | const layoutPath = path.join(newAppDirPath, '_layout.tsx');
65 | fs.writeFile(layoutPath, layoutContent, (error) => {
66 | if (error) {
67 | return console.error(`Error creating _layout.tsx: ${error}`);
68 | }
69 | console.log('app/_layout.tsx created.');
70 | });
71 | });
72 | });
73 | });
74 |
--------------------------------------------------------------------------------
/app/index.tsx:
--------------------------------------------------------------------------------
1 | import {Image, Platform, StyleSheet, Text, useWindowDimensions, View} from "react-native";
2 | import {easeGradient} from "react-native-easing-gradient";
3 | import MaskedView from "@react-native-masked-view/masked-view";
4 | import {LinearGradient} from "expo-linear-gradient";
5 | import {BlurView} from "expo-blur";
6 | import Animated, {
7 | interpolate,
8 | useAnimatedScrollHandler,
9 | useAnimatedStyle,
10 | useSharedValue
11 | } from "react-native-reanimated";
12 |
13 | export default function Index() {
14 | const {width, height} = useWindowDimensions()
15 | // PARALLAX SCROLL
16 | const scrollY = useSharedValue(0)
17 | const onScroll = useAnimatedScrollHandler({
18 | onScroll: ({ contentOffset: { y } }) => {
19 | scrollY.value = -y;
20 | },
21 | })
22 | const imageContainerStyle = useAnimatedStyle(() => ({
23 | transform: [{scale: interpolate(scrollY.value, [0, height], [1, 2])}]
24 | }))
25 | // LINEAR GRADIENT
26 | const { colors, locations } = easeGradient({
27 | colorStops: {0: {color: 'transparent'},0.5: {color: 'rgba(0,0,0,0.99)'}, 1: {color: 'black'}},
28 | })
29 | return (
30 |
33 |
36 |
37 |
40 |
41 |
43 |
50 | }
51 | style={[StyleSheet.absoluteFill]}>
52 |
55 |
56 |
57 | Hello World
58 |
59 |
60 |
61 | );
62 | }
63 |
64 | const styles = StyleSheet.create({
65 | container: {
66 | flex: 1
67 | },
68 | blurContainer: {
69 | position: 'absolute',
70 | bottom: 0,
71 | zIndex: 2,
72 | },
73 | linearGradient: {
74 | bottom: 0,
75 | position: 'absolute',
76 | },
77 | textContainer: {
78 | alignItems: 'center',
79 | justifyContent: 'center',
80 | flex: 1
81 | },
82 | text: {
83 | color: 'white',
84 | fontSize: 40,
85 | fontWeight: 'bold'
86 | }
87 | })
88 |
--------------------------------------------------------------------------------