├── .gitignore
├── .npmignore
├── .prettierrc
├── LICENSE
├── README.md
├── index.js
├── lib
├── animated
│ ├── AnimatedBar.js
│ └── AnimatedCircle.js
├── const
│ └── index.js
├── loader
│ ├── BreathingLoader.js
│ ├── BubblesLoader.js
│ ├── CirclesLoader.js
│ ├── CirclesRotationScaleLoader.js
│ ├── ColorDotsLoader.js
│ ├── DotsLoader.js
│ ├── DoubleCircleLoader.js
│ ├── EatBeanLoader.js
│ ├── LineDotsLoader.js
│ ├── LinesLoader.js
│ ├── MusicLoader.js
│ ├── NineCubesLoader.js
│ ├── OpacityDotsLoader.js
│ ├── PulseLoader.js
│ ├── RippleLoader.js
│ ├── RotationCircleLoader.js
│ ├── RotationHoleLoader.js
│ └── TextLoader.js
└── shape
│ ├── Bar.js
│ ├── Bar2.js
│ ├── Bar3.js
│ └── Circle.js
├── package-lock.json
├── package.json
└── screenshot
├── ss1.gif
├── ss2.gif
├── ss3.gif
└── ss4.gif
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea
2 | /node_modules
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | /screenshot
2 | /.idea
3 | /node_modules
4 | .prettierrc
5 | README.md
6 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 100,
3 | "trailingComma": "all",
4 | "tabWidth": 2,
5 | "semi": true,
6 | "singleQuote": true,
7 | "bracketSpacing": true,
8 | "arrowParens": "always"
9 | }
10 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | MIT License
3 |
4 | Copyright (c) 2016 Di Wang
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-native-indicator
2 |
3 |   [](https://www.npmjs.com/package/react-native-indicator)
4 |
5 | A useful indicator component for React Native
6 |
7 |
8 |
9 |
10 |
11 |
12 | ## Installation
13 |
14 | Make sure that you are in your React Native project directory and run:
15 | ```
16 | $ npm install react-native-indicator --save
17 | $ npm install @react-native-community/art --save
18 | ```
19 |
20 | For react-native >= 0.60 ReactNativeART should be auto-linked and no additional action is required.
21 |
22 | For react-native < 0.60 you need to link ReactNative ART:
23 | ```
24 | $ react-native link @react-native-community/art
25 | ```
26 |
27 | More info, following the [Art module](https://github.com/react-native-community/art) instruction to configure.
28 |
29 | ## Usage
30 |
31 | Import react-native-indicator as a JavaScript module:
32 | ```
33 | import { CirclesLoader, PulseLoader, TextLoader, DotsLoader, ... } from 'react-native-indicator';
34 | ```
35 |
36 | Here is currently available types:
37 |
38 | - [PulseLoader](#PulseLoader)
39 | - [DotsLoader](#DotsLoader)
40 | - [TextLoader](#TextLoader)
41 | - [BubblesLoader](#BubblesLoader)
42 | - [CirclesLoader](#CirclesLoader)
43 | - [BreathingLoader](#BreathingLoader)
44 | - [RippleLoader](#RippleLoader)
45 | - [LinesLoader](#LinesLoader)
46 | - [MusicBarLoader](#MusicBarLoader)
47 | - [EatBeanLoader](#EatBeanLoader)
48 | - [DoubleCircleLoader](#DoubleCircleLoader)
49 | - [RotationCircleLoader](#RotationCircleLoader)
50 | - [RotationHoleLoader](#RotationHoleLoader)
51 | - [CirclesRotationScaleLoader](#CirclesRotationScaleLoader)
52 | - [NineCubesLoader](#NineCubesLoader)
53 | - [LineDotsLoader](#LineDotsLoader)
54 | - [ColorDotsLoader](#ColorDotsLoader)
55 | - [OpacityDotsLoader](#OpacityDotsLoader)
56 |
57 | ```
58 | render(){
59 | return(
60 |
61 |
62 |
63 |
64 | );
65 | }
66 | ```
67 |
68 | ## Props
69 |
70 |
71 |
72 | ##### PulseLoader
73 |
74 | | prop | type | default | description |
75 | | ---- | ---- | ---- | ---- |
76 | | size | number | 30 | circle's size |
77 | | color | string | '#1e90ff' | indicator's color |
78 | | frequency | number | 1000 | scale's frequency |
79 |
80 |
81 |
82 |
83 | ##### DotsLoader
84 |
85 | | prop | type | default | description |
86 | | ---- | ---- | ---- | ---- |
87 | | size | number | 10 | dot's size |
88 | | color | string | '#1e90ff' | indicator's color |
89 | | betweenSpace | number | 5 | distance between two dots |
90 |
91 |
92 |
93 |
94 | ##### TextLoader
95 |
96 | | prop | type | default | description |
97 | | ---- | ---- | ---- | ---- |
98 | | text | string | 'Loading' | contents |
99 | | textStyle | style | inherited | text's style |
100 |
101 |
102 |
103 |
104 | ##### BubblesLoader
105 |
106 | | prop | type | default | description |
107 | | ---- | ---- | ---- | ---- |
108 | | size | number | 40 | circle's size |
109 | | color | string | '#1e90ff' | indicator's color |
110 | | dotRadius | number | 10 | each dot's size |
111 |
112 |
113 |
114 |
115 | ##### CirclesLoader
116 |
117 | | prop | type | default | description |
118 | | ---- | ---- | ---- | ---- |
119 | | size | number | 40 | circle's size |
120 | | color | string | '#1e90ff' | indicator's color |
121 | | dotRadius | number | 8 | each dot's size |
122 |
123 |
124 |
125 |
126 | ##### BreathingLoader
127 |
128 | | prop | type | default | description |
129 | | ---- | ---- | ---- | ---- |
130 | | size | number | 10 | circle's size |
131 | | color | string | '#1e90ff' | indicator's color |
132 | | strokeWidth | number | 3 | outline width |
133 | | frequency | number | 800 | scale's frequency |
134 |
135 |
136 |
137 |
138 | ##### RippleLoader
139 |
140 | | prop | type | default | description |
141 | | ---- | ---- | ---- | ---- |
142 | | size | number | 10 | circle's size |
143 | | frequency | number | 1600 | scale's frequency |
144 | | color | string | '#1e90ff' | indicator's color |
145 | | strokeWidth | number | 3 | outline width |
146 |
147 |
148 |
149 |
150 | ##### LinesLoader
151 |
152 | | prop | type | default | description |
153 | | ---- | ---- | ---- | ---- |
154 | | color | string | '#1e90ff' | indicator's color |
155 | | barWidth | number | 5 | each bar's width |
156 | | barHeight | number | 40 | each bar's height |
157 | | barNumber | number | 5 | the number of bar |
158 | | betweenSpace | number | 2 | distance between two bars |
159 |
160 |
161 |
162 |
163 | ##### MusicBarLoader
164 |
165 | | prop | type | default | description |
166 | | ---- | ---- | ---- | ---- |
167 | | color | string | '#1e90ff' | indicator's color |
168 | | barWidth | number | 3 | each bar's width |
169 | | barHeight | number | 30 | each bar's height |
170 | | betweenSpace | number | 5 | distance between two bars |
171 |
172 |
173 |
174 |
175 | ##### EatBeanLoader
176 |
177 | | prop | type | default | description |
178 | | ---- | ---- | ---- | ---- |
179 | | color | string | '#1e90ff' | indicator's color |
180 | | size | number | 30 | indicator's size |
181 |
182 |
183 |
184 |
185 | ##### DoubleCircleLoader
186 |
187 | | prop | type | default | description |
188 | | ---- | ---- | ---- | ---- |
189 | | size | number | 30 | circle's size |
190 | | color | string | '#1e90ff' | indicator's color |
191 |
192 |
193 |
194 |
195 | ##### RotationCircleLoader
196 |
197 | | prop | type | default | description |
198 | | ---- | ---- | ---- | ---- |
199 | | size | number | 30 | indicator's size |
200 | | color | string | '#1e90ff' | indicator's color |
201 | | rotationSpeed | number | 800 | rotation speed |
202 |
203 |
204 |
205 |
206 | ##### RotationHoleLoader
207 |
208 | | prop | type | default | description |
209 | | ---- | ---- | ---- | ---- |
210 | | size | number | 40 | indicator's size |
211 | | color | string | '#1e90ff' | indicator's color |
212 | | rotationSpeed | number | 800 | rotation speed |
213 | | strokeWidth | number | 8 | circle outline's width |
214 |
215 |
216 |
217 |
218 | ##### CirclesRotationScaleLoader
219 |
220 | | prop | type | default | description |
221 | | ---- | ---- | ---- | ---- |
222 | | size | number | 50 | indicator's size |
223 | | color | string | '#1e90ff' | indicator's color |
224 |
225 |
226 |
227 |
228 | ##### NineCubesLoader
229 |
230 | | prop | type | default | description |
231 | | ---- | ---- | ---- | ---- |
232 | | size | number | 20 | each cube's size |
233 | | color | string | '#1e90ff' | indicator's color |
234 |
235 |
236 |
237 |
238 | ##### LineDotsLoader
239 |
240 | **warning:** *this indicator will occupy a whole horizontal space automatically, which means you don't need to set any center props. Just keeping the direction of its parent View is vertical.*
241 |
242 | | prop | type | default | description |
243 | | ---- | ---- | ---- | ---- |
244 | | size | number | 10 | dot's size |
245 | | color | string | '#1e90ff' | indicator's color |
246 | | dotsNumber | number | 5 | the number of dots |
247 | | betweenSpace | number | 5 | distance between two dots |
248 |
249 |
250 |
251 |
252 | ##### ColorDotsLoader
253 |
254 | | prop | type | default | description |
255 | | ---- | ---- | ---- | ---- |
256 | | size | number | 15 | each cube's size |
257 | | betweenSpace | number | 7 | distance between two dots |
258 | | color1 | string | '#ff4500'(red) | 1st color |
259 | | color2 | string | '#ffd700'(yellow) | 2nd color |
260 | | color3 | string | '#9acd32'(green) | 3rd color |
261 |
262 | ##### OpacityDotsLoader
263 |
264 | | prop | type | default | description |
265 | | ---- | ---- | ---- | ---- |
266 | | size | number | 10 | dot's size |
267 | | color | string | '#1e90ff' | indicator's color |
268 | | betweenSpace | number | 5 | distance between two dots |
269 | | speed | number | 200 | change speed |
270 |
271 | ## License
272 |
273 | MIT
274 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import Breathing from './lib/loader/BreathingLoader';
2 | import Bubbles from './lib/loader/BubblesLoader';
3 | import Circles from './lib/loader/CirclesLoader';
4 | import CirclesRotationScale from './lib/loader/CirclesRotationScaleLoader';
5 | import ColorDots from './lib/loader/ColorDotsLoader';
6 | import Dots from './lib/loader/DotsLoader';
7 | import DoubleCircle from './lib/loader/DoubleCircleLoader';
8 | import EatBean from './lib/loader/EatBeanLoader';
9 | import Lines from './lib/loader/LinesLoader';
10 | import LineDots from './lib/loader/LineDotsLoader';
11 | import Music from './lib/loader/MusicLoader';
12 | import NineCubes from './lib/loader/NineCubesLoader';
13 | import OpacityDots from './lib/loader/OpacityDotsLoader';
14 | import Pulse from './lib/loader/PulseLoader';
15 | import Ripple from './lib/loader/RippleLoader';
16 | import RotationCircle from './lib/loader/RotationCircleLoader';
17 | import RotationHole from './lib/loader/RotationHoleLoader';
18 | import Text from './lib/loader/TextLoader';
19 |
20 | export const BreathingLoader = Breathing;
21 | export const BubblesLoader = Bubbles;
22 | export const CirclesLoader = Circles;
23 | export const CirclesRotationScaleLoader = CirclesRotationScale;
24 | export const ColorDotsLoader = ColorDots;
25 | export const DotsLoader = Dots;
26 | export const DoubleCircleLoader = DoubleCircle;
27 | export const EatBeanLoader = EatBean;
28 | export const LinesLoader = Lines;
29 | export const LineDotsLoader = LineDots;
30 | export const MusicBarLoader = Music;
31 | export const NineCubesLoader = NineCubes;
32 | export const OpacityDotsLoader = OpacityDots;
33 | export const PulseLoader = Pulse;
34 | export const RippleLoader = Ripple;
35 | export const RotationCircleLoader = RotationCircle;
36 | export const RotationHoleLoader = RotationHole;
37 | export const TextLoader = Text;
38 |
--------------------------------------------------------------------------------
/lib/animated/AnimatedBar.js:
--------------------------------------------------------------------------------
1 | import Bar from '../shape/Bar';
2 | import { Animated } from 'react-native';
3 |
4 | export default Animated.createAnimatedComponent(Bar);
5 |
--------------------------------------------------------------------------------
/lib/animated/AnimatedCircle.js:
--------------------------------------------------------------------------------
1 | import Circle from '../shape/Circle';
2 | import { Animated } from 'react-native';
3 |
4 | export default Animated.createAnimatedComponent(Circle);
5 |
--------------------------------------------------------------------------------
/lib/const/index.js:
--------------------------------------------------------------------------------
1 | export const color = '#1e90ff';
2 |
--------------------------------------------------------------------------------
/lib/loader/BreathingLoader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Animated } from 'react-native';
4 | import { Surface } from '@react-native-community/art';
5 | import AnimatedCircle from '../animated/AnimatedCircle';
6 | import { color } from '../const';
7 |
8 | export default class BreathingLoader extends React.PureComponent {
9 | static propTypes = {
10 | color: PropTypes.string,
11 | size: PropTypes.number,
12 | strokeWidth: PropTypes.number,
13 | frequency: PropTypes.number,
14 | };
15 |
16 | static defaultProps = {
17 | color,
18 | size: 30,
19 | strokeWidth: 3,
20 | frequency: 800,
21 | };
22 |
23 | constructor(props) {
24 | super(props);
25 | this.state = {
26 | scale: new Animated.Value(0.1),
27 | };
28 | }
29 |
30 | componentDidMount() {
31 | this._animation();
32 | }
33 |
34 | componentWillUnmount() {
35 | this.unmounted = true;
36 | }
37 |
38 | _animation = () => {
39 | Animated.sequence([
40 | Animated.timing(this.state.scale, {
41 | toValue: 1,
42 | duration: this.props.frequency,
43 | useNativeDriver: false,
44 | }),
45 | Animated.timing(this.state.scale, {
46 | toValue: 0.1,
47 | duration: this.props.frequency,
48 | useNativeDriver: false,
49 | }),
50 | ]).start(() => {
51 | !this.unmounted && this._animation();
52 | });
53 | };
54 |
55 | render() {
56 | const { color, size, strokeWidth } = this.props;
57 | return (
58 |
59 |
67 |
68 | );
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/lib/loader/BubblesLoader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Animated } from 'react-native';
4 | import { Surface } from '@react-native-community/art';
5 | import AnimatedCircle from '../animated/AnimatedCircle';
6 | import { color } from '../const';
7 |
8 | export default class BubblesLoader extends React.PureComponent {
9 | static propTypes = {
10 | color: PropTypes.string,
11 | dotRadius: PropTypes.number,
12 | size: PropTypes.number,
13 | };
14 |
15 | static defaultProps = {
16 | color,
17 | dotRadius: 10,
18 | size: 40,
19 | };
20 |
21 | state = {
22 | opacities: [
23 | new Animated.Value(1),
24 | new Animated.Value(1),
25 | new Animated.Value(1),
26 | new Animated.Value(1),
27 | new Animated.Value(1),
28 | new Animated.Value(1),
29 | new Animated.Value(1),
30 | new Animated.Value(1),
31 | ],
32 | };
33 | eachDegree = 360 / this.state.opacities.length;
34 | timers = [];
35 |
36 | componentDidMount() {
37 | this.state.opacities.forEach((item, i) => {
38 | const id = setTimeout(() => {
39 | this._animation(i);
40 | }, i * 150);
41 | this.timers.push(id);
42 | });
43 | }
44 |
45 | componentWillUnmount() {
46 | this.unmounted = true;
47 | this.timers.forEach((id) => {
48 | clearTimeout(id);
49 | });
50 | }
51 |
52 | _animation = (i) => {
53 | Animated.sequence([
54 | Animated.timing(this.state.opacities[i], {
55 | toValue: 0.2,
56 | duration: 600,
57 | useNativeDriver: false,
58 | }),
59 | Animated.timing(this.state.opacities[i], {
60 | toValue: 1,
61 | duration: 600,
62 | useNativeDriver: false,
63 | }),
64 | ]).start(() => {
65 | !this.unmounted && this._animation(i);
66 | });
67 | };
68 |
69 | render() {
70 | const { size, dotRadius, color } = this.props;
71 | const { opacities } = this.state;
72 | return (
73 |
74 | {opacities.map((item, i) => {
75 | let radian = (i * this.eachDegree * Math.PI) / 180;
76 | let x = Math.round((size / 2) * Math.cos(radian)) + size / 2 + dotRadius / 2;
77 | let y = Math.round((size / 2) * Math.sin(radian)) + size / 2 + dotRadius / 2;
78 | return (
79 |
87 | );
88 | })}
89 |
90 | );
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/lib/loader/CirclesLoader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Animated } from 'react-native';
4 | import { Surface } from '@react-native-community/art';
5 | import AnimatedCircle from '../animated/AnimatedCircle';
6 | import { color } from '../const';
7 |
8 | export default class CirclesLoader extends React.PureComponent {
9 | static propTypes = {
10 | color: PropTypes.string,
11 | dotRadius: PropTypes.number,
12 | size: PropTypes.number,
13 | };
14 |
15 | static defaultProps = {
16 | color,
17 | dotRadius: 8,
18 | size: 40,
19 | };
20 |
21 | state = {
22 | opacities: [
23 | new Animated.Value(1),
24 | new Animated.Value(1),
25 | new Animated.Value(1),
26 | new Animated.Value(1),
27 | new Animated.Value(1),
28 | new Animated.Value(1),
29 | new Animated.Value(1),
30 | new Animated.Value(1),
31 | ],
32 | };
33 | eachDegree = 360 / this.state.opacities.length;
34 | timers = [];
35 |
36 | componentDidMount() {
37 | this.state.opacities.forEach((item, i) => {
38 | const id = setTimeout(() => {
39 | this._animation(i);
40 | }, i * 150);
41 | this.timers.push(id);
42 | });
43 | }
44 |
45 | componentWillUnmount() {
46 | this.unmounted = true;
47 | this.timers.forEach((id) => {
48 | clearTimeout(id);
49 | });
50 | }
51 |
52 | _animation = (i) => {
53 | Animated.sequence([
54 | Animated.timing(this.state.opacities[i], {
55 | toValue: 0.1,
56 | duration: 600,
57 | useNativeDriver: false,
58 | }),
59 | Animated.timing(this.state.opacities[i], {
60 | toValue: 1,
61 | duration: 600,
62 | useNativeDriver: false,
63 | }),
64 | ]).start(() => {
65 | !this.unmounted && this._animation(i);
66 | });
67 | };
68 |
69 | render() {
70 | const { size, dotRadius, color } = this.props;
71 | const { opacities } = this.state;
72 | return (
73 |
74 | {opacities.map((item, i) => {
75 | let radian = (i * this.eachDegree * Math.PI) / 180;
76 | let x = Math.round((size / 2) * Math.cos(radian)) + size / 2 + dotRadius / 2;
77 | let y = Math.round((size / 2) * Math.sin(radian)) + size / 2 + dotRadius / 2;
78 | return (
79 |
87 | );
88 | })}
89 |
90 | );
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/lib/loader/CirclesRotationScaleLoader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Animated, Easing } from 'react-native';
4 | import { Surface, Group } from '@react-native-community/art';
5 | import AnimatedCircle from '../animated/AnimatedCircle';
6 | import { color } from '../const';
7 |
8 | export default class RotationCircleLoader extends React.PureComponent {
9 | static propTypes = {
10 | size: PropTypes.number,
11 | color: PropTypes.string,
12 | };
13 |
14 | static defaultProps = {
15 | size: 50,
16 | color,
17 | };
18 |
19 | state = {
20 | degree: new Animated.Value(0),
21 | scales: [new Animated.Value(0), new Animated.Value(0)]
22 | };
23 | timers = [];
24 |
25 | componentDidMount() {
26 | this._animation();
27 | this.state.scales.forEach((item, i) => {
28 | const id = setTimeout(() => {
29 | this._animationCircles(i)
30 | }, i * 500);
31 | this.timers.push(id);
32 | });
33 |
34 | }
35 |
36 | componentWillUnmount() {
37 | this.unmounted = true;
38 | this.timers.forEach((id) => {
39 | clearTimeout(id);
40 | });
41 | }
42 |
43 | _animation = () => {
44 | Animated.sequence([
45 | Animated.timing(this.state.degree, {
46 | toValue: 360,
47 | duration: 2000,
48 | easing: Easing.linear,
49 | useNativeDriver: false
50 | })
51 | ]).start(() => {
52 | if (!this.unmounted) {
53 | this.state.degree.setValue(0);
54 | this._animation();
55 | }
56 | });
57 | };
58 |
59 | _animationCircles = (i) => {
60 | Animated.sequence([
61 | Animated.timing(this.state.scales[i], { toValue: 1, duration: 1000, useNativeDriver: false }),
62 | Animated.timing(this.state.scales[i], {
63 | toValue: 0.05,
64 | duration: 1000,
65 | useNativeDriver: false
66 | }),
67 | ]).start(() => {
68 | !this.unmounted && this._animationCircles(i);
69 | });
70 | };
71 |
72 | render() {
73 | const { size, color } = this.props;
74 | const degree = this.state.degree.interpolate({
75 | inputRange: [0, 360],
76 | outputRange: ['0deg', '360deg']
77 | });
78 | return (
79 |
86 |
87 |
88 |
95 |
102 |
103 |
104 |
105 | );
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/lib/loader/ColorDotsLoader.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Animated, Easing } from 'react-native';
4 | import { Surface, Group } from '@react-native-community/art';
5 | import AnimatedCircle from '../animated/AnimatedCircle';
6 |
7 | export default class ColorDotsLoader extends Component {
8 | static propTypes = {
9 | size: PropTypes.number,
10 | betweenSpace: PropTypes.number,
11 | color1: PropTypes.string,
12 | color2: PropTypes.string,
13 | color3: PropTypes.string,
14 | };
15 |
16 | static defaultProps = {
17 | size: 15,
18 | betweenSpace: 7,
19 | color1: '#ff4500',
20 | color2: '#ffd700',
21 | color3: '#9acd32',
22 | };
23 |
24 | constructor(props) {
25 | super(props);
26 | const red = this.props.color1;
27 | const yellow = this.props.color2;
28 | const green = this.props.color3;
29 | this.state = {
30 | colors: [red, red, red],
31 | color: yellow,
32 | x: new Animated.Value(-this.props.size / 2),
33 | };
34 | this.patterns = [
35 | [yellow, red, red],
36 | [yellow, yellow, red],
37 | [yellow, yellow, yellow],
38 | [green, yellow, yellow],
39 | [green, green, yellow],
40 | [green, green, green],
41 | [red, green, green],
42 | [red, red, green],
43 | [red, red, red],
44 | ];
45 | this.timers = [];
46 | }
47 |
48 | componentDidMount() {
49 | this._animation();
50 | }
51 |
52 | componentWillUnmount() {
53 | this.unmounted = true;
54 | this.timers.forEach((id) => {
55 | clearTimeout(id);
56 | });
57 | }
58 |
59 | _animation = () => {
60 | const { size, betweenSpace, color1, color2, color3 } = this.props;
61 | const id1 = setTimeout(() => {
62 | this.setState({ color: color3 });
63 | }, 600);
64 | const id2 = setTimeout(() => {
65 | this.setState({ color: color1 });
66 | }, 1200);
67 | this.timers.push(id1);
68 | this.timers.push(id2);
69 | this.patterns.forEach((item, i) => {
70 | const id = setTimeout(() => {
71 | this.setState({ colors: this.patterns[i] });
72 | }, i * 200 + 100);
73 | this.timers.push(id);
74 | });
75 |
76 | Animated.sequence([
77 | Animated.timing(this.state.x, {
78 | toValue: size * 3 + betweenSpace * 2 + size / 2,
79 | duration: 600,
80 | easing: Easing.linear,
81 | useNativeDriver: false,
82 | }),
83 | Animated.timing(this.state.x, {
84 | toValue: -size / 2,
85 | duration: 0,
86 | useNativeDriver: false,
87 | }),
88 | Animated.timing(this.state.x, {
89 | toValue: size * 3 + betweenSpace * 2 + size / 2,
90 | duration: 600,
91 | easing: Easing.linear,
92 | useNativeDriver: false,
93 | }),
94 | Animated.timing(this.state.x, {
95 | toValue: -size / 2,
96 | duration: 0,
97 | useNativeDriver: false,
98 | }),
99 | Animated.timing(this.state.x, {
100 | toValue: size * 3 + betweenSpace * 2 + size / 2,
101 | duration: 600,
102 | easing: Easing.linear,
103 | useNativeDriver: false,
104 | }),
105 | ]).start(() => {
106 | if (!this.unmounted) {
107 | this.state.x.setValue(-size / 2);
108 | this.setState({ color: color2 });
109 | this._animation();
110 | }
111 | });
112 | };
113 |
114 | render() {
115 | const { size, betweenSpace } = this.props;
116 | const { color, colors } = this.state;
117 | return (
118 |
119 |
120 | {colors.map((item, i) => (
121 |
128 | ))}
129 |
130 |
131 |
132 | );
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/lib/loader/DotsLoader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Animated } from 'react-native';
4 | import { Surface } from '@react-native-community/art';
5 | import AnimatedCircle from '../animated/AnimatedCircle';
6 | import { color } from '../const';
7 |
8 | export default class DotsLoader extends React.PureComponent {
9 | static propTypes = {
10 | color: PropTypes.string,
11 | size: PropTypes.number,
12 | betweenSpace: PropTypes.number,
13 | };
14 |
15 | static defaultProps = {
16 | color,
17 | size: 10,
18 | betweenSpace: 5,
19 | };
20 |
21 | state = {
22 | scales: [new Animated.Value(0), new Animated.Value(0), new Animated.Value(0)],
23 | };
24 |
25 | componentDidMount() {
26 | this._animation();
27 | }
28 |
29 | componentWillUnmount() {
30 | this.unmounted = true;
31 | }
32 |
33 | _animation = () => {
34 | function seq(self, i) {
35 | return Animated.sequence([
36 | Animated.timing(self.state.scales[i], {
37 | toValue: 1,
38 | duration: 300,
39 | delay: (i + 1) * 200,
40 | useNativeDriver: false,
41 | }),
42 | Animated.timing(self.state.scales[i], {
43 | toValue: 0,
44 | duration: 300,
45 | delay: 50,
46 | useNativeDriver: false,
47 | }),
48 | ]);
49 | }
50 |
51 | Animated.parallel([seq(this, 0), seq(this, 1), seq(this, 2)]).start(() => {
52 | if (!this.unmounted) this._animation();
53 | });
54 | };
55 |
56 | _renderCircle = (i) => {
57 | const { color, size, betweenSpace } = this.props;
58 | return (
59 |
66 | );
67 | };
68 |
69 | render() {
70 | const { size, betweenSpace } = this.props;
71 | return (
72 |
73 | {this._renderCircle(0)}
74 | {this._renderCircle(1)}
75 | {this._renderCircle(2)}
76 |
77 | );
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/lib/loader/DoubleCircleLoader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Animated } from 'react-native';
4 | import { Surface } from '@react-native-community/art';
5 | import AnimatedCircle from '../animated/AnimatedCircle';
6 | import { color } from '../const';
7 |
8 | export default class DoubleCircleLoader extends React.PureComponent {
9 | static propTypes = {
10 | color: PropTypes.string,
11 | size: PropTypes.number,
12 | };
13 |
14 | static defaultProps = {
15 | color,
16 | size: 30,
17 | };
18 |
19 | state = {
20 | scales: [new Animated.Value(0), new Animated.Value(0)],
21 | };
22 | timers = [];
23 |
24 | componentDidMount() {
25 | this.state.scales.forEach((item, i) => {
26 | const id = setTimeout(() => {
27 | this._animation(i);
28 | }, i * 1000);
29 | this.timers.push(id);
30 | });
31 | }
32 |
33 | componentWillUnmount() {
34 | this.unmounted = true;
35 | this.timers.forEach((id) => {
36 | clearTimeout(id);
37 | });
38 | }
39 |
40 | _animation = (i) => {
41 | Animated.sequence([
42 | Animated.timing(this.state.scales[i], { toValue: 1, duration: 1000, useNativeDriver: false }),
43 | Animated.timing(this.state.scales[i], { toValue: 0, duration: 1000, useNativeDriver: false }),
44 | ]).start(() => {
45 | !this.unmounted && this._animation(i);
46 | });
47 | };
48 |
49 | render() {
50 | const { color, size } = this.props;
51 | const { scales } = this.state;
52 | return (
53 |
54 |
62 |
70 |
71 | );
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/lib/loader/EatBeanLoader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Animated } from 'react-native';
4 | import { Surface, Shape } from '@react-native-community/art';
5 | import AnimatedCircle from '../animated/AnimatedCircle';
6 | import { color } from '../const';
7 |
8 | export default class EatBeanLoader extends React.PureComponent {
9 | static propTypes = {
10 | size: PropTypes.number,
11 | color: PropTypes.string,
12 | };
13 |
14 | static defaultProps = {
15 | size: 30,
16 | color,
17 | };
18 |
19 | state = {
20 | dotsY: [
21 | new Animated.Value(this.props.size * 2.2),
22 | new Animated.Value(this.props.size * 2.2),
23 | new Animated.Value(this.props.size * 2.2),
24 | new Animated.Value(this.props.size * 2.2),
25 | ],
26 | };
27 | timers = [];
28 |
29 | componentDidMount() {
30 | this.state.dotsY.forEach((item, i) => {
31 | const id = setTimeout(() => {
32 | this._animation(i);
33 | }, i * 300);
34 | this.timers.push(id);
35 | });
36 | }
37 |
38 | componentWillUnmount() {
39 | this.unmounted = true;
40 | this.timers.forEach((id) => {
41 | clearTimeout(id);
42 | });
43 | }
44 |
45 | _animation = (i) => {
46 | Animated.timing(this.state.dotsY[i], {
47 | toValue: this.props.size / 2,
48 | duration: 1200,
49 | useNativeDriver: false,
50 | }).start(() => {
51 | if (!this.unmounted) {
52 | this.state.dotsY[i].setValue(this.props.size * 2.2);
53 | this._animation(i);
54 | }
55 | });
56 | };
57 |
58 | render() {
59 | const { size, color } = this.props;
60 |
61 | const sinValue = Math.sqrt(2) / 2;
62 | const x = Math.floor((size / 2) * sinValue) + size / 2;
63 | const startY = Math.floor((size / 2) * sinValue) + size / 2;
64 | const endY = size / 2 - Math.floor((size / 2) * sinValue);
65 | const d = `M${x} ${startY} A ${size / 2} ${size / 2}, 0, 1, 1, ${x} ${endY} L ${size /
66 | 2} ${size / 2} Z`;
67 | return (
68 |
69 |
70 | {this.state.dotsY.map((item, i) => (
71 |
72 | ))}
73 |
74 | );
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/lib/loader/LineDotsLoader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Animated, Dimensions } from 'react-native';
4 | import { Surface } from '@react-native-community/art';
5 | import AnimatedCircle from '../animated/AnimatedCircle';
6 | import { color } from '../const';
7 |
8 | export default class LineDotsLoader extends React.PureComponent {
9 | static propTypes = {
10 | color: PropTypes.string,
11 | size: PropTypes.number,
12 | dotsNumber: PropTypes.number,
13 | betweenSpace: PropTypes.number,
14 | };
15 |
16 | static defaultProps = {
17 | color,
18 | size: 10,
19 | dotsNumber: 5,
20 | betweenSpace: 5,
21 | };
22 |
23 | constructor(props) {
24 | super(props);
25 | this.screenWidth = Dimensions.get('window').width;
26 | const { size, dotsNumber, betweenSpace } = this.props;
27 | const midX =
28 | this.screenWidth / 2 + (size * dotsNumber + betweenSpace * (dotsNumber - 1)) / 2 - size / 2;
29 | let circlesX = [];
30 | this.beginX = [];
31 | this.centerX = [];
32 | this.destX = [];
33 | for (let i = 0; i < dotsNumber; i++) {
34 | let beginX = -size / 2 - (size + betweenSpace) * i;
35 | circlesX.push(new Animated.Value(beginX));
36 | this.beginX.push(beginX);
37 | this.centerX.push(midX - i * (size + betweenSpace));
38 | this.destX.push(this.screenWidth + size / 2 + i * (size + betweenSpace));
39 | }
40 |
41 | this.state = {
42 | x: circlesX,
43 | };
44 | }
45 |
46 | render() {
47 | const { color, size } = this.props;
48 | return (
49 |
50 | {this.state.x.map((item, i) => (
51 |
52 | ))}
53 |
54 | );
55 | }
56 |
57 | componentDidMount() {
58 | this._animation();
59 | }
60 |
61 | componentWillUnmount() {
62 | this.unmounted = true;
63 | }
64 |
65 | _animation = () => {
66 | this.state.x.forEach((item, i) => {
67 | Animated.sequence([
68 | Animated.timing(this.state.x[i], {
69 | toValue: this.centerX[i],
70 | duration: 600,
71 | delay: i * 50,
72 | useNativeDriver: false,
73 | }),
74 | Animated.timing(this.state.x[i], {
75 | toValue: this.centerX[i],
76 | duration: 600,
77 | delay: 300,
78 | useNativeDriver: false,
79 | }),
80 | Animated.timing(this.state.x[i], {
81 | toValue: this.destX[i],
82 | duration: 600,
83 | delay: i * 50,
84 | useNativeDriver: false,
85 | }),
86 | ]).start(() => {
87 | if (i === this.props.dotsNumber - 1) {
88 | for (let idx in this.state.x) {
89 | this.state.x[idx].setValue(this.beginX[idx]);
90 | }
91 | !this.unmounted && this._animation();
92 | }
93 | });
94 | });
95 | };
96 | }
97 |
--------------------------------------------------------------------------------
/lib/loader/LinesLoader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Animated } from 'react-native';
4 | import { Surface } from '@react-native-community/art';
5 | import AnimatedBar from '../animated/AnimatedBar';
6 | import { color } from '../const';
7 |
8 | export default class LinesLoader extends React.PureComponent {
9 | static propTypes = {
10 | color: PropTypes.string,
11 | barWidth: PropTypes.number,
12 | barHeight: PropTypes.number,
13 | betweenSpace: PropTypes.number,
14 | barNumber: PropTypes.number,
15 | };
16 |
17 | static defaultProps = {
18 | color,
19 | betweenSpace: 2,
20 | barNumber: 5,
21 | barWidth: 5,
22 | barHeight: 40,
23 | };
24 |
25 | constructor(props) {
26 | super(props);
27 | const heights = [];
28 | for (let i = 0; i < this.props.barNumber; i++) {
29 | heights.push(new Animated.Value(this.props.barHeight / 3));
30 | }
31 |
32 | this.state = {
33 | heights,
34 | };
35 | }
36 |
37 | componentDidMount() {
38 | this._animation();
39 | }
40 |
41 | componentWillUnmount() {
42 | this.unmounted = true;
43 | }
44 |
45 | _animation = () => {
46 | function seq(self, i) {
47 | return Animated.sequence([
48 | Animated.timing(self.state.heights[i], {
49 | toValue: self.props.barHeight,
50 | duration: 400,
51 | delay: i * 200,
52 | useNativeDriver: false,
53 | }),
54 | Animated.timing(self.state.heights[i], {
55 | toValue: self.props.barHeight / 3,
56 | duration: 400,
57 | useNativeDriver: false,
58 | }),
59 | ]);
60 | }
61 |
62 | const anim = [];
63 | for (let i = 0; i < this.props.barNumber; i++) anim.push(seq(this, i));
64 |
65 | Animated.parallel(anim).start(() => {
66 | !this.unmounted && this._animation();
67 | });
68 | };
69 |
70 | render() {
71 | const { color, betweenSpace, barWidth, barHeight, barNumber } = this.props;
72 | return (
73 |
74 | {this.state.heights.map((item, i) => (
75 |
83 | ))}
84 |
85 | );
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/lib/loader/MusicLoader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Animated } from 'react-native';
4 | import { Surface } from '@react-native-community/art';
5 | import Bar from '../shape/Bar2';
6 | import { color } from '../const';
7 |
8 | const AnimatedBar = Animated.createAnimatedComponent(Bar);
9 |
10 | export default class LinesLoader extends React.PureComponent {
11 | static propTypes = {
12 | color: PropTypes.string,
13 | barWidth: PropTypes.number,
14 | barHeight: PropTypes.number,
15 | betweenSpace: PropTypes.number,
16 | };
17 |
18 | static defaultProps = {
19 | color,
20 | betweenSpace: 5,
21 | barWidth: 3,
22 | barHeight: 30,
23 | };
24 |
25 | constructor(props) {
26 | super(props);
27 | this.fixedMaxValue = [
28 | this.props.barHeight * 0.8,
29 | this.props.barHeight * 0.4,
30 | this.props.barHeight,
31 | this.props.barHeight * 0.2,
32 | ];
33 | this.fixedMinValue = [
34 | this.props.barHeight * 0.3,
35 | this.props.barHeight,
36 | this.props.barHeight * 0.5,
37 | this.props.barHeight * 0.8,
38 | ];
39 |
40 | this.state = {
41 | heights: [
42 | new Animated.Value(this.fixedMinValue[0]),
43 | new Animated.Value(this.fixedMinValue[1]),
44 | new Animated.Value(this.fixedMinValue[2]),
45 | new Animated.Value(this.fixedMinValue[3]),
46 | ],
47 | };
48 | }
49 |
50 | componentDidMount() {
51 | this.state.heights.forEach((item, i) => {
52 | this._animation(i);
53 | });
54 | }
55 |
56 | componentWillUnmount() {
57 | this.unmounted = true;
58 | }
59 |
60 | _animation = (i) => {
61 | Animated.sequence([
62 | Animated.timing(this.state.heights[i], {
63 | toValue: this.fixedMaxValue[i],
64 | duration: 500,
65 | useNativeDriver: false,
66 | }),
67 | Animated.timing(this.state.heights[i], {
68 | toValue: this.fixedMinValue[i],
69 | duration: 500,
70 | useNativeDriver: false,
71 | }),
72 | ]).start(() => {
73 | !this.unmounted && this._animation(i);
74 | });
75 | };
76 |
77 | render() {
78 | const { color, betweenSpace, barWidth, barHeight, barNumber } = this.props;
79 | return (
80 |
81 | {this.state.heights.map((item, i) => {
82 | return (
83 |
91 | );
92 | })}
93 |
94 | );
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/lib/loader/NineCubesLoader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Animated } from 'react-native';
4 | import { Surface } from '@react-native-community/art';
5 | import Bar3 from '../shape/Bar3';
6 | import { color } from '../const';
7 |
8 | const AnimatedBar = Animated.createAnimatedComponent(Bar3);
9 |
10 | export default class NineCubesLoader extends React.PureComponent {
11 | state = {
12 | scales: [
13 | new Animated.Value(0),
14 | new Animated.Value(0),
15 | new Animated.Value(0),
16 | new Animated.Value(0),
17 | new Animated.Value(0),
18 | ],
19 | };
20 |
21 | static propTypes = {
22 | size: PropTypes.number,
23 | color: PropTypes.string,
24 | };
25 |
26 | static defaultProps = {
27 | size: 20,
28 | color,
29 | };
30 |
31 | _renderCube(i, j, scaleID) {
32 | const { size, color } = this.props;
33 | return (
34 |
42 | );
43 | }
44 |
45 | render() {
46 | const { size, color } = this.props;
47 | return (
48 |
49 | {this._renderCube(0, 0, 2)}
50 | {this._renderCube(0, 1, 1)}
51 | {this._renderCube(0, 2, 0)}
52 | {this._renderCube(1, 0, 3)}
53 | {this._renderCube(1, 1, 2)}
54 | {this._renderCube(1, 2, 1)}
55 | {this._renderCube(2, 0, 4)}
56 | {this._renderCube(2, 1, 3)}
57 | {this._renderCube(2, 2, 2)}
58 |
59 | );
60 | }
61 |
62 | componentDidMount() {
63 | this._animation();
64 | }
65 |
66 | componentWillUnmount() {
67 | this.unmounted = true;
68 | }
69 |
70 | _animation = () => {
71 | function seq(self, i) {
72 | return Animated.sequence([
73 | Animated.timing(self.state.scales[i], {
74 | toValue: 1,
75 | duration: 300,
76 | delay: (i + 1) * 100,
77 | useNativeDriver: false,
78 | }),
79 | Animated.timing(self.state.scales[i], {
80 | toValue: 0,
81 | duration: 300,
82 | delay: 200,
83 | useNativeDriver: false,
84 | }),
85 | ]);
86 | }
87 |
88 | Animated.parallel([seq(this, 0), seq(this, 1), seq(this, 2), seq(this, 3), seq(this, 4)]).start(
89 | () => {
90 | !this.unmounted && this._animation();
91 | },
92 | );
93 | };
94 | }
95 |
--------------------------------------------------------------------------------
/lib/loader/OpacityDotsLoader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Animated } from 'react-native';
4 | import { Surface } from '@react-native-community/art';
5 | import AnimatedCircle from '../animated/AnimatedCircle';
6 | import { color } from '../const';
7 |
8 | export default class OpacityDotsLoader extends React.PureComponent {
9 | static propTypes = {
10 | color: PropTypes.string,
11 | size: PropTypes.number,
12 | betweenSpace: PropTypes.number,
13 | speed: PropTypes.number,
14 | };
15 |
16 | static defaultProps = {
17 | color,
18 | size: 10,
19 | betweenSpace: 5,
20 | speed: 200,
21 | };
22 |
23 | state = {
24 | opacity: [new Animated.Value(0.5), new Animated.Value(0.5), new Animated.Value(0.5)],
25 | };
26 |
27 | _renderCircle(i) {
28 | const { color, size, betweenSpace } = this.props;
29 | return (
30 |
38 | );
39 | }
40 |
41 | componentDidMount() {
42 | this._animation();
43 | }
44 |
45 | componentWillUnmount() {
46 | this.unmounted = true;
47 | }
48 |
49 | _animation = () => {
50 | const { speed } = this.props;
51 |
52 | function seq(self, i) {
53 | return Animated.sequence([
54 | Animated.timing(self.state.opacity[i], {
55 | toValue: 1,
56 | duration: speed,
57 | delay: i * speed,
58 | useNativeDriver: false,
59 | }),
60 | Animated.timing(self.state.opacity[i], {
61 | toValue: 0.3,
62 | duration: speed,
63 | delay: speed,
64 | useNativeDriver: false,
65 | }),
66 | ]);
67 | }
68 |
69 | Animated.parallel([seq(this, 0), seq(this, 1), seq(this, 2)]).start(() => {
70 | !this.unmounted && this._animation();
71 | });
72 | };
73 |
74 | render() {
75 | const { size, betweenSpace } = this.props;
76 | return (
77 |
78 | {this._renderCircle(0)}
79 | {this._renderCircle(1)}
80 | {this._renderCircle(2)}
81 |
82 | );
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/lib/loader/PulseLoader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Animated } from 'react-native';
4 | import { Surface } from '@react-native-community/art';
5 | import AnimatedCircle from '../animated/AnimatedCircle';
6 | import { color } from '../const';
7 |
8 | export default class PulseLoader extends React.PureComponent {
9 | static propTypes = {
10 | color: PropTypes.string,
11 | size: PropTypes.number,
12 | frequency: PropTypes.number,
13 | };
14 |
15 | static defaultProps = {
16 | color,
17 | size: 30,
18 | frequency: 1000,
19 | };
20 |
21 | state = {
22 | effect: new Animated.ValueXY({ x: 0, y: 1 }),
23 | };
24 |
25 | componentDidMount() {
26 | this._animation();
27 | }
28 |
29 | componentWillUnmount() {
30 | this.unmounted = true;
31 | }
32 |
33 | _animation = () => {
34 | Animated.parallel([
35 | Animated.timing(this.state.effect.x, {
36 | toValue: 1,
37 | duration: this.props.frequency,
38 | useNativeDriver: false,
39 | }),
40 | Animated.timing(this.state.effect.y, {
41 | toValue: 0.05,
42 | duration: this.props.frequency,
43 | useNativeDriver: false,
44 | }),
45 | ]).start(() => {
46 | if (!this.unmounted) {
47 | this.state.effect.setValue({ x: 0, y: 1 });
48 | this._animation();
49 | }
50 | });
51 | };
52 |
53 | render() {
54 | const { color, size } = this.props;
55 | return (
56 |
57 |
65 |
66 | );
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/lib/loader/RippleLoader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Animated } from 'react-native';
4 | import { Surface } from '@react-native-community/art';
5 | import AnimatedCircle from '../animated/AnimatedCircle';
6 | import { color } from '../const';
7 |
8 | export default class RippleLoader extends React.PureComponent {
9 | static propTypes = {
10 | color: PropTypes.string,
11 | size: PropTypes.number,
12 | strokeWidth: PropTypes.number,
13 | frequency: PropTypes.number,
14 | };
15 |
16 | static defaultProps = {
17 | color,
18 | size: 40,
19 | strokeWidth: 3,
20 | frequency: 1600,
21 | };
22 |
23 | state = {
24 | scales: [new Animated.Value(0.1), new Animated.Value(0.1)],
25 | opacities: [new Animated.Value(1), new Animated.Value(1)],
26 | };
27 | timers = [];
28 |
29 | componentDidMount() {
30 | this.state.scales.forEach((item, i) => {
31 | const id = setTimeout(() => {
32 | this._animation(i);
33 | }, i * this.props.frequency * 0.75);
34 | this.timers.push(id);
35 | });
36 | }
37 |
38 | componentWillUnmount() {
39 | this.unmounted = true;
40 | this.timers.forEach((id) => {
41 | clearTimeout(id);
42 | });
43 | }
44 |
45 | _animation = (i) => {
46 | const { frequency } = this.props;
47 | Animated.parallel([
48 | Animated.timing(this.state.scales[i], {
49 | toValue: 1,
50 | duration: frequency,
51 | useNativeDriver: false,
52 | }),
53 | Animated.timing(this.state.opacities[i], {
54 | toValue: 0,
55 | duration: frequency,
56 | delay: frequency / 2,
57 | useNativeDriver: false,
58 | }),
59 | ]).start(() => {
60 | if (!this.unmounted) {
61 | this.state.scales[i].setValue(0.1);
62 | this.state.opacities[i].setValue(1);
63 | this._animation(i);
64 | }
65 | });
66 | };
67 |
68 | render() {
69 | const { color, size, strokeWidth } = this.props;
70 | const { scales, opacities } = this.state;
71 | return (
72 |
73 | {scales.map((item, i) => (
74 |
84 | ))}
85 |
86 | );
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/lib/loader/RotationCircleLoader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Animated, Easing } from 'react-native';
4 | import { Surface, Group } from '@react-native-community/art';
5 | import AnimatedCircle from '../animated/AnimatedCircle';
6 | import { color } from '../const';
7 |
8 | export default class RotationCircleLoader extends React.PureComponent {
9 | static propTypes = {
10 | size: PropTypes.number,
11 | color: PropTypes.string,
12 | rotationSpeed: PropTypes.number
13 | };
14 |
15 | static defaultProps = {
16 | size: 40,
17 | color,
18 | rotationSpeed: 800
19 | };
20 |
21 | state = {
22 | degree: new Animated.Value(0)
23 | };
24 |
25 | componentDidMount() {
26 | this._animation();
27 | }
28 |
29 | componentWillUnmount() {
30 | this.unmounted = true;
31 | }
32 |
33 | _animation = () => {
34 | Animated.sequence([
35 | Animated.timing(this.state.degree, {
36 | toValue: 360,
37 | duration: this.props.rotationSpeed,
38 | easing: Easing.linear,
39 | useNativeDriver: false
40 | })
41 | ]).start(() => {
42 | if (!this.unmounted) {
43 | this.state.degree.setValue(0);
44 | this._animation();
45 | }
46 | });
47 | };
48 |
49 | render() {
50 | const { size, color } = this.props;
51 | const degree = this.state.degree.interpolate({
52 | inputRange: [0, 360],
53 | outputRange: ['0deg', '360deg']
54 | });
55 | return (
56 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | );
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/lib/loader/RotationHoleLoader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Animated, Easing } from 'react-native';
4 | import { Surface, Group } from '@react-native-community/art';
5 | import AnimatedCircle from '../animated/AnimatedCircle';
6 | import { color } from '../const';
7 |
8 | export default class RotationHoleLoader extends React.PureComponent {
9 | static propTypes = {
10 | size: PropTypes.number,
11 | color: PropTypes.string,
12 | strokeWith: PropTypes.number,
13 | rotationSpeed: PropTypes.number
14 | };
15 |
16 | static defaultProps = {
17 | size: 40,
18 | color,
19 | rotationSpeed: 800,
20 | strokeWith: 8
21 | };
22 |
23 | state = {
24 | degree: new Animated.Value(0)
25 | };
26 |
27 | componentDidMount() {
28 | this._animation();
29 | }
30 |
31 | componentWillUnmount() {
32 | this.unmounted = true;
33 | }
34 |
35 | _animation = () => {
36 | Animated.sequence([
37 | Animated.timing(this.state.degree, {
38 | toValue: 360,
39 | duration: this.props.rotationSpeed,
40 | easing: Easing.linear,
41 | useNativeDriver: false
42 | })
43 | ]).start(() => {
44 | if (!this.unmounted) {
45 | this.state.degree.setValue(0);
46 | this._animation();
47 | }
48 | });
49 | };
50 |
51 | render() {
52 | const { size, color, strokeWith } = this.props;
53 | const degree = this.state.degree.interpolate({
54 | inputRange: [0, 360],
55 | outputRange: ['0deg', '360deg']
56 | });
57 | return (
58 |
65 |
66 |
67 |
75 |
81 |
82 |
83 |
84 | );
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/lib/loader/TextLoader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Text, View } from 'react-native';
4 |
5 | export default class TextLoader extends React.PureComponent {
6 | static propTypes = {
7 | text: PropTypes.string,
8 | textStyle: Text.propTypes.style,
9 | };
10 |
11 | static defaultProps = {
12 | text: 'Loading',
13 | };
14 |
15 | state = {
16 | opacities: [0, 0, 0],
17 | };
18 | patterns = [[0, 0, 0], [1, 0, 0], [1, 1, 0], [1, 1, 1]];
19 | timers = [];
20 |
21 | componentDidMount() {
22 | this._animation(1);
23 | }
24 |
25 | componentWillUnmount() {
26 | this.unmounted = true;
27 | this.timers.forEach((id) => {
28 | clearTimeout(id);
29 | });
30 | }
31 |
32 | _animation = (index) => {
33 | if (!this.unmounted) {
34 | const id = setTimeout(() => {
35 | this.setState({ opacities: this.patterns[index] });
36 | index++;
37 | if (index >= this.patterns.length) index = 0;
38 | this._animation(index);
39 | }, 500);
40 | this.timers.push(id);
41 | }
42 | };
43 |
44 | render() {
45 | const { text, textStyle } = this.props;
46 | return (
47 |
48 | {text}
49 | {this.state.opacities.map((item, i) => (
50 |
51 | .
52 |
53 | ))}
54 |
55 | );
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/lib/shape/Bar.js:
--------------------------------------------------------------------------------
1 | /**
2 | * The scale center of this bar is left-center
3 | */
4 | import React from 'react';
5 | import PropTypes from 'prop-types';
6 | import { Shape, Path } from '@react-native-community/art';
7 |
8 | export default class Bar extends React.PureComponent {
9 | static propTypes = {
10 | width: PropTypes.number.isRequired,
11 | height: PropTypes.number.isRequired,
12 | };
13 |
14 | render() {
15 | const { width, height } = this.props;
16 |
17 | const path = Path()
18 | .moveTo(width, height / 2)
19 | .lineTo(0, height / 2)
20 | .lineTo(0, -height / 2)
21 | .lineTo(width, -height / 2)
22 | .close();
23 |
24 | return ;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/shape/Bar2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * The scale center of this bar is bottom-center
3 | */
4 | import React from 'react';
5 | import PropTypes from 'prop-types';
6 | import { Shape, Path } from '@react-native-community/art';
7 |
8 | export default class Bar2 extends React.PureComponent {
9 | static propTypes = {
10 | width: PropTypes.number.isRequired,
11 | height: PropTypes.number.isRequired,
12 | };
13 |
14 | render() {
15 | const { width, height } = this.props;
16 |
17 | const path = Path()
18 | .moveTo(0, 0)
19 | .lineTo(0, -height)
20 | .lineTo(width, -height)
21 | .lineTo(width, 0)
22 | .close();
23 |
24 | return ;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/shape/Bar3.js:
--------------------------------------------------------------------------------
1 | /**
2 | * The scale center of this bar is center
3 | */
4 | import React from 'react';
5 | import PropTypes from 'prop-types';
6 | import { Shape, Path } from '@react-native-community/art';
7 |
8 | export default class Bar3 extends React.PureComponent {
9 | static propTypes = {
10 | width: PropTypes.number.isRequired,
11 | height: PropTypes.number.isRequired,
12 | };
13 |
14 | render() {
15 | const { width, height } = this.props;
16 |
17 | const path = Path()
18 | .moveTo(width / 2, height / 2)
19 | .lineTo(-width / 2, height / 2)
20 | .lineTo(-width / 2, -height / 2)
21 | .lineTo(width / 2, -height / 2)
22 | .close();
23 |
24 | return ;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/shape/Circle.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Shape, Path } from '@react-native-community/art';
4 |
5 | export default class Circle extends React.PureComponent {
6 | static propTypes = {
7 | radius: PropTypes.number.isRequired,
8 | opacity: PropTypes.number,
9 | };
10 |
11 | render() {
12 | const { radius } = this.props;
13 |
14 | const path = Path()
15 | .moveTo(0, -radius / 2)
16 | .arc(0, radius, 1)
17 | .arc(0, -radius, 1)
18 | .close();
19 |
20 | return ;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-indicator",
3 | "version": "1.0.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "js-tokens": {
8 | "version": "4.0.0",
9 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
10 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
11 | },
12 | "loose-envify": {
13 | "version": "1.4.0",
14 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
15 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
16 | "requires": {
17 | "js-tokens": "^3.0.0 || ^4.0.0"
18 | }
19 | },
20 | "object-assign": {
21 | "version": "4.1.1",
22 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
23 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
24 | },
25 | "prettier": {
26 | "version": "1.19.1",
27 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz",
28 | "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==",
29 | "dev": true
30 | },
31 | "prop-types": {
32 | "version": "15.7.2",
33 | "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
34 | "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
35 | "requires": {
36 | "loose-envify": "^1.4.0",
37 | "object-assign": "^4.1.1",
38 | "react-is": "^16.8.1"
39 | }
40 | },
41 | "react-is": {
42 | "version": "16.8.6",
43 | "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz",
44 | "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA=="
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-indicator",
3 | "version": "1.2.2",
4 | "description": "React Native Indicator Component",
5 | "main": "index.js",
6 | "scripts": {
7 | "lint": "./node_modules/.bin/prettier --config .prettierrc --write lib/**/*.js",
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/wangdicoder/react-native-indicator.git"
13 | },
14 | "keywords": [
15 | "react-native",
16 | "indicator",
17 | "loader",
18 | "progress"
19 | ],
20 | "author": "Di Wang ",
21 | "license": "MIT",
22 | "bugs": {
23 | "url": "https://github.com/wangdicoder/react-native-indicator/issues"
24 | },
25 | "homepage": "https://github.com/wangdicoder/react-native-indicator#readme",
26 | "dependencies": {
27 | "prop-types": "^15.6.0"
28 | },
29 | "devDependencies": {
30 | "prettier": "^1.19.1"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/screenshot/ss1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdicoder/react-native-indicator/666e616e40a2f8942457ee9631463665b4dc5bb7/screenshot/ss1.gif
--------------------------------------------------------------------------------
/screenshot/ss2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdicoder/react-native-indicator/666e616e40a2f8942457ee9631463665b4dc5bb7/screenshot/ss2.gif
--------------------------------------------------------------------------------
/screenshot/ss3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdicoder/react-native-indicator/666e616e40a2f8942457ee9631463665b4dc5bb7/screenshot/ss3.gif
--------------------------------------------------------------------------------
/screenshot/ss4.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdicoder/react-native-indicator/666e616e40a2f8942457ee9631463665b4dc5bb7/screenshot/ss4.gif
--------------------------------------------------------------------------------