├── .gitignore
├── README.md
├── apple-app-of-the-day
├── App.js
├── README.md
├── app.json
├── assets
│ ├── icons
│ │ ├── app-icon.png
│ │ └── loading-icon.png
│ ├── images
│ │ ├── 1.jpg
│ │ ├── 2.jpg
│ │ ├── 3.jpg
│ │ └── 4.jpg
│ └── snack-icon.png
├── components
│ └── AssetExample.js
└── package.json
└── case-gif
├── app-store-today-demo.gif
└── lottery-demo.gif
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-native-showcase
2 |
3 | 记录React Native的各种动画、交互Case,供大家参考使用,欢迎大家Star。
4 |
5 | ## Table of Contents
6 |
7 | * [九宫格抽奖转盘](#react-native-lottery)
8 |
9 | * [仿App Store Today页](#apple-app-store-today)
10 |
11 | * [自定义下拉刷新header组件](#react-native-pull-to-refresh-custom)
12 |
13 | * [motion-manager实现卡片动感光效动画](#react-native-motion-event-manager)
14 |
15 | ## react-native-lottery
16 |
17 | **React Native使用的9宫格抽奖转盘。**
18 |
19 | 
20 |
21 | [expo在线Demo](https://snack.expo.io/@wangcheng714/react-native-lottery)
22 |
23 | 开源组件 [react-native-super-lottery](https://github.com/rrd-fe/react-native-super-lottery)
24 |
25 | ## apple-app-store-today
26 |
27 | **仿照苹果应用商店`Today`页面的动画效果**
28 |
29 | 
30 |
31 | [expo在线Demo](https://snack.expo.io/@wangcheng714/apple-app-of-the-day)
32 |
33 | 实现文档 [React Native 实现 App Store Today页效果](https://github.com/rrd-fe/blog/blob/master/react-native/app-today-page.md)
34 |
35 | ## react-native-pull-to-refresh-custom
36 |
37 | **自定义下拉刷新header组件**
38 |
39 | 
40 |
41 | [expo demo](https://snack.expo.io/@sophister/custom-pull-to-refresh-header)
42 |
43 | [github source](https://github.com/sophister/react-native-pull-to-refresh-custom)
44 |
45 | ## react-native-motion-event-manager
46 |
47 | **利用motion-manager实现卡片动感光效动画**
48 |
49 | 
50 |
51 | [React Native中如原生般流畅地使用设备传感器](https://github.com/rrd-fe/blog/blob/master/react-native/motion-event.md)
52 |
53 | [github source](https://github.com/rrd-fe/react-native-motion-event-manager)
54 |
--------------------------------------------------------------------------------
/apple-app-of-the-day/App.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {
3 | Text,
4 | View,
5 | Image,
6 | Alert,
7 | Animated,
8 | StyleSheet,
9 | ScrollView,
10 | Dimensions,
11 | SafeAreaView,
12 | TouchableWithoutFeedback,
13 | } from 'react-native';
14 |
15 | const Images = [
16 | require('./assets/images/1.jpg'),
17 | require('./assets/images/2.jpg'),
18 | require('./assets/images/3.jpg'),
19 | require('./assets/images/4.jpg'),
20 | ];
21 |
22 | const SCREEN_HEIGHT = Dimensions.get('window').height;
23 | const SCREEN_WIDTH = Dimensions.get('window').width;
24 |
25 | export default class App extends React.Component {
26 |
27 | constructor(props) {
28 | super(props);
29 | this.imageRef = [];
30 | this.oldPosition = {};
31 | // 描述图片的位置变化
32 | this.position = new Animated.ValueXY();
33 | // 描述图片的大小变化
34 | this.measure = new Animated.ValueXY();
35 | // 其他动画公用变量
36 | this.animation = new Animated.Value(0);
37 | this.state = {
38 | activeImage: null,
39 | }
40 | }
41 |
42 | openImage = (index) => {
43 | this.imageRef[index].measure((x, y, width, height, pageX, pageY) => {
44 | // 记录图片点击的时候位置,关闭详情视图的时候需要还原回去
45 | this.oldPosition = {
46 | width,
47 | height,
48 | x: pageX,
49 | y: pageY,
50 | };
51 |
52 | // 初始化动画变量,准备开始动画
53 | this.position.setValue({
54 | x: pageX,
55 | y: pageY,
56 | });
57 | this.measure.setValue({
58 | x: width,
59 | y: height,
60 | });
61 |
62 | this.setState(() => {
63 | return {
64 | activeImage: Images[index],
65 | }
66 | }, () => {
67 | this.imageContainer.measure((x, y, width, height, pageX, pageY) => {
68 | Animated.parallel([
69 | Animated.timing(this.position.x, {
70 | toValue: pageX,
71 | duration: 300,
72 | }),
73 | Animated.timing(this.position.y, {
74 | toValue: pageY,
75 | duration: 300,
76 | }),
77 | Animated.timing(this.measure.x, {
78 | toValue: width,
79 | duration: 300,
80 | }),
81 | Animated.timing(this.measure.y, {
82 | toValue: height,
83 | duration: 300,
84 | }),
85 | Animated.timing(this.animation, {
86 | toValue: 1,
87 | duration: 300,
88 | }),
89 | ]).start();
90 | });
91 | });
92 |
93 | });
94 | }
95 |
96 | closeImage = () => {
97 | Animated.parallel([
98 | Animated.timing(this.position.x, {
99 | toValue: this.oldPosition.x,
100 | duration: 300,
101 | }),
102 | Animated.timing(this.position.y, {
103 | toValue: this.oldPosition.y,
104 | duration: 250,
105 | }),
106 | Animated.timing(this.measure.x, {
107 | toValue: this.oldPosition.width,
108 | duration: 250,
109 | }),
110 | Animated.timing(this.measure.y, {
111 | toValue: this.oldPosition.height,
112 | duration: 250,
113 | }),
114 | Animated.timing(this.animation, {
115 | toValue: 0,
116 | duration: 250,
117 | }),
118 | ]).start(() => {
119 | this.setState(() => {
120 | return {
121 | activeImage: null
122 | }
123 | });
124 | });
125 | }
126 |
127 | render() {
128 |
129 | const imageBorderAnimate = this.animation.interpolate({
130 | inputRange: [0, 0, 1],
131 | outputRange: [20, 10, 0]
132 | });
133 | // 设置图片的动画
134 | const imageAnimatedStyle = {
135 | top: this.position.y,
136 | left: this.position.x,
137 | width: this.measure.x,
138 | height: this.measure.y,
139 | borderRadius: imageBorderAnimate,
140 | };
141 |
142 | const contentOpacityAnimate = this.animation.interpolate({
143 | inputRange: [0, 0.5, 1],
144 | outputRange: [0, 1, 1]
145 | });
146 |
147 | const contentYAnimate = this.animation.interpolate({
148 | inputRange: [0, 1],
149 | outputRange: [-150, 0]
150 | });
151 | // 设置内容的动画
152 | const contentAnimatedStyle = {
153 | opacity: contentOpacityAnimate,
154 | transform: [{
155 | translateY: contentYAnimate,
156 | }]
157 | }
158 | // 设置关闭按钮的动画
159 | const croseAnimatedStyle = {
160 | opacity: this.animation
161 | };
162 |
163 | return (
164 |
165 |
166 | {
167 | Images.map((image, index) => {
168 | return (
169 | { this.openImage(index); }}>
170 |
173 | { this.imageRef[index] = image; }}
175 | source={image}
176 | style={{ flex: 1, height: null, width: null, resizeMode: 'cover', borderRadius: 20, }}
177 | />
178 |
179 |
180 | );
181 | })
182 | }
183 |
184 |
188 | { this.imageContainer = view; }}>
189 |
195 |
199 |
203 | X
204 |
205 |
206 |
207 |
211 | 这是图片的Title
212 | 这是图片的内容区域
213 |
214 |
215 |
216 | );
217 | }
218 | }
219 |
220 |
--------------------------------------------------------------------------------
/apple-app-of-the-day/README.md:
--------------------------------------------------------------------------------
1 | # Apple App of the day
2 |
3 | 模仿苹果App Store Today 页面的动画效果,实现React Native版本
4 |
5 | ## 实现步骤
6 |
7 | 1. 实现基本的列表布局
8 | 2. 实现打开详情页效果
9 | 3. 实现关闭详情页效果
--------------------------------------------------------------------------------
/apple-app-of-the-day/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "expo": {
3 | "name": "apple-app-of-the-day",
4 | "description": "No description",
5 | "slug": "snack-SJtwp_2gH",
6 | "privacy": "unlisted",
7 | "sdkVersion": "33.0.0",
8 | "version": "1.0.0",
9 | "orientation": "portrait",
10 | "primaryColor": "#cccccc",
11 | "icon": "https://d1wp6m56sqw74a.cloudfront.net/~assets/c9aa1be8a6a6fe81e20c3ac4106a2ebc",
12 | "loading": {
13 | "icon": "https://d1wp6m56sqw74a.cloudfront.net/~assets/c9aa1be8a6a6fe81e20c3ac4106a2ebc",
14 | "hideExponentText": false
15 | },
16 | "packagerOpts": {
17 | "assetExts": [
18 | "ttf",
19 | "mp4",
20 | "otf",
21 | "xml"
22 | ]
23 | },
24 | "ios": {
25 | "supportsTablet": true
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/apple-app-of-the-day/assets/icons/app-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rrd-fe/react-native-showcase/470f745eb5d2cea7d878e58148b20a8db4711fcd/apple-app-of-the-day/assets/icons/app-icon.png
--------------------------------------------------------------------------------
/apple-app-of-the-day/assets/icons/loading-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rrd-fe/react-native-showcase/470f745eb5d2cea7d878e58148b20a8db4711fcd/apple-app-of-the-day/assets/icons/loading-icon.png
--------------------------------------------------------------------------------
/apple-app-of-the-day/assets/images/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rrd-fe/react-native-showcase/470f745eb5d2cea7d878e58148b20a8db4711fcd/apple-app-of-the-day/assets/images/1.jpg
--------------------------------------------------------------------------------
/apple-app-of-the-day/assets/images/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rrd-fe/react-native-showcase/470f745eb5d2cea7d878e58148b20a8db4711fcd/apple-app-of-the-day/assets/images/2.jpg
--------------------------------------------------------------------------------
/apple-app-of-the-day/assets/images/3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rrd-fe/react-native-showcase/470f745eb5d2cea7d878e58148b20a8db4711fcd/apple-app-of-the-day/assets/images/3.jpg
--------------------------------------------------------------------------------
/apple-app-of-the-day/assets/images/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rrd-fe/react-native-showcase/470f745eb5d2cea7d878e58148b20a8db4711fcd/apple-app-of-the-day/assets/images/4.jpg
--------------------------------------------------------------------------------
/apple-app-of-the-day/assets/snack-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rrd-fe/react-native-showcase/470f745eb5d2cea7d878e58148b20a8db4711fcd/apple-app-of-the-day/assets/snack-icon.png
--------------------------------------------------------------------------------
/apple-app-of-the-day/components/AssetExample.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { Text, View, StyleSheet, Image } from 'react-native';
3 |
4 | export default class AssetExample extends React.Component {
5 | render() {
6 | return (
7 |
8 |
9 | Local files and assets can be imported by dragging and dropping them into the editor
10 |
11 |
12 |
13 | );
14 | }
15 | }
16 |
17 | const styles = StyleSheet.create({
18 | container: {
19 | alignItems: 'center',
20 | justifyContent: 'center',
21 | padding: 24,
22 | },
23 | paragraph: {
24 | margin: 24,
25 | marginTop: 0,
26 | fontSize: 14,
27 | fontWeight: 'bold',
28 | textAlign: 'center',
29 | },
30 | logo: {
31 | height: 128,
32 | width: 128,
33 | }
34 | });
35 |
--------------------------------------------------------------------------------
/apple-app-of-the-day/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "apple-app-of-the-day",
3 | "version": "0.0.0",
4 | "description": "No description",
5 | "author": null,
6 | "private": true,
7 | "main": "node_modules/expo/AppEntry.js",
8 | "dependencies": {
9 | "expo": "^33.0.0",
10 | "react": "16.8.3",
11 | "react-native": "https://github.com/expo/react-native/archive/sdk-33.0.0.tar.gz",
12 | "react-native-paper": "2.15.2"
13 | }
14 | }
--------------------------------------------------------------------------------
/case-gif/app-store-today-demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rrd-fe/react-native-showcase/470f745eb5d2cea7d878e58148b20a8db4711fcd/case-gif/app-store-today-demo.gif
--------------------------------------------------------------------------------
/case-gif/lottery-demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rrd-fe/react-native-showcase/470f745eb5d2cea7d878e58148b20a8db4711fcd/case-gif/lottery-demo.gif
--------------------------------------------------------------------------------