├── .gitignore
├── LICENSE
├── README.md
├── index.js
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (http://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # Typescript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 echoplans
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-native-rotating-text
2 |
3 | [](https://badge.fury.io/js/react-native-rotating-text)
4 |
5 | 
6 |
7 | A typewriter type effect for text in react native. React-native port of react-rotating-text.
8 |
9 | ## Installation
10 |
11 | ```
12 | npm install react-native-rotating-text --save
13 | ```
14 |
15 | ## Usage
16 |
17 | ```jsx
18 | import RotatingText from 'react-native-rotating-text'
19 |
20 |
24 | ```
25 |
26 | ### Properties
27 |
28 | **style (*number*)**
29 | *(default: {})*
30 | Any style object you want to appy on Text.
31 |
32 | **items (*array*)**
33 | *(default: ['first', 'second', 'third'])*
34 | The array of strings to be cycled through.
35 |
36 | **color (*string*)**
37 | *(default: 'inherit')*
38 | This specifies the color of the text.
39 |
40 | **cursor (*boolean*)**
41 | *(default: true)*
42 | If set to true, it will display the cursor after the text.
43 |
44 | **pause (*integer*)**
45 | *(default: 1500)*
46 | The number of milliseconds to pause after the text has just finished being typed out.
47 |
48 | **emptyPause (*integer*)**
49 | *(default: 1000)*
50 | The number of milliseconds to pause while no text is being displayed (i.e. after deleting has just finished).
51 |
52 | **eraseMode (*string*)**
53 | *(default: 'erase')*
54 | This specifies the erasing mode. May be set to "erase" or "overwrite".
55 |
56 | **typingInterval (*integer*)**
57 | *(default: 50)*
58 | The number of milliseconds between each typing action.
59 |
60 | **deletingInterval (*integer*)**
61 | *(default: 50)*
62 | The number of milliseconds between each deleting action.
63 |
64 | ## License
65 | [MIT](https://github.com/echoplans/react-native-rotating-text/blob/master/LICENSE)
66 |
67 | ## Inspiration
68 | https://github.com/adrianmcli/react-rotating-text
69 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author srijan02420
3 | * @last-modified 2017-05-31
4 | * @repo
5 | */
6 |
7 | import React, { PureComponent } from 'react';
8 | import {
9 | Text
10 | } from 'react-native';
11 | import PropTypes from 'prop-types';
12 |
13 | export default class RotatingText extends PureComponent {
14 |
15 | constructor(props) {
16 | super(props);
17 | this.state = {
18 | index: 0,
19 | output: '',
20 | substrLength: 0,
21 | };
22 | this.timeouts = [];
23 | }
24 |
25 | componentDidMount() {
26 | this._animate.bind(this)(); // begin the animation loop
27 | }
28 |
29 | componentWillUnmount() {
30 | this.timeouts.map(x => clearTimeout(x)); // stop all the loops
31 | }
32 |
33 | _loop(loopingFunc, pause) {
34 | // save the timeouts so we can stop on unmount
35 | const timeout = setTimeout(loopingFunc, pause);
36 | this.timeouts.push(timeout);
37 |
38 | // prevent memory leak
39 | const maxTimeouts = 100;
40 | if (this.timeouts.length > maxTimeouts) {
41 | clearTimeout(this.timeouts[0]);
42 | this.timeouts.shift();
43 | }
44 | }
45 |
46 | _type(text, callback) {
47 | const { output } = this.state;
48 | const { typingInterval } = this.props;
49 | const loopingFunc = this._type.bind(this, text, callback);
50 |
51 | // set the string one character longer
52 | this.setState({output: text.substr(0, output.length + 1)});
53 |
54 | // if we're still not done, recursively loop again
55 | if (output.length < text.length) {
56 | this._loop(loopingFunc, typingInterval);
57 | } else {
58 | callback();
59 | }
60 | }
61 |
62 | _erase(callback) {
63 | const { output } = this.state;
64 | const { deletingInterval } = this.props;
65 | const loopingFunc = this._erase.bind(this, callback);
66 |
67 | // set the string one character shorter
68 | this.setState({output: output.substr(0, output.length - 1)});
69 |
70 | // if we're still not done, recursively loop again
71 | if (output.length !== 0) {
72 | this._loop(loopingFunc, deletingInterval);
73 | } else {
74 | callback();
75 | }
76 | };
77 |
78 | _overwrite(text, callback) {
79 | const { output, substrLength } = this.state;
80 | const { deletingInterval } = this.props;
81 | const loopingFunc = this._overwrite.bind(this, text, callback);
82 |
83 | this.setState({
84 | output: text.substr(0, substrLength) + output.substr(substrLength),
85 | substrLength: substrLength + 1,
86 | });
87 |
88 | if (text.length !== substrLength) {
89 | this._loop(loopingFunc, deletingInterval);
90 | } else {
91 | this.setState({
92 | output: text,
93 | substrLength: 0,
94 | });
95 | callback();
96 | }
97 | };
98 |
99 | _animate() {
100 | const { index } = this.state;
101 | const { items, pause, emptyPause, eraseMode } = this.props;
102 | const type = this._type;
103 | const erase = this._erase;
104 | const overwrite = this._overwrite;
105 | const loopingFunc = this._animate.bind(this);
106 | const nextIndex = index === items.length - 1 ? 0 : index + 1;
107 |
108 | const nextWord = () => {
109 | this.setState({index: nextIndex});
110 | this._loop(loopingFunc, emptyPause);
111 | };
112 |
113 | type.bind(this)(items[index], () => {
114 | if (eraseMode === 'overwrite') {
115 | this._loop(overwrite.bind(this, items[nextIndex], nextWord), pause);
116 | } else {
117 | this._loop(erase.bind(this, nextWord), pause);
118 | }
119 | });
120 | };
121 |
122 | render() {
123 | const {
124 | style,
125 | cursor,
126 | deletingInterval,
127 | emptyPause,
128 | items,
129 | pause,
130 | eraseMode,
131 | typingInterval,
132 | ...other
133 | } = this.props;
134 |
135 | return (
136 |
137 | { this.state.output }
138 | { cursor ? | : null }
139 |
140 | );
141 | }
142 | }
143 |
144 | RotatingText.propTypes = {
145 | style: PropTypes.object,
146 | cursor: PropTypes.bool,
147 | deletingInterval: PropTypes.number,
148 | emptyPause: PropTypes.number,
149 | eraseMode: PropTypes.string,
150 | items: PropTypes.array,
151 | pause: PropTypes.number,
152 | typingInterval: PropTypes.number,
153 | };
154 |
155 | RotatingText.defaultProps = {
156 | style: {},
157 | cursor: true,
158 | deletingInterval: 50,
159 | emptyPause: 1000,
160 | eraseMode: 'erase',
161 | items: ['first', 'second', 'third'],
162 | pause: 1500,
163 | typingInterval: 50,
164 | };
165 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-rotating-text",
3 | "version": "0.0.2",
4 | "description": "A react-native port for react-rotating-text. For ios as well as android.",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "srijan02420",
10 | "license": "MIT",
11 | "repository": {
12 | "type": "git",
13 | "url": "https://github.com/echoplans/react-native-rotating-text"
14 | },
15 | "keywords": [
16 | "react-native",
17 | "react-native-rotating-text",
18 | "rotating-text"
19 | ],
20 | "bugs": {
21 | "url": "https://github.com/echoplans/react-native-rotating-text/issues"
22 | },
23 | "dependencies": {
24 | "prop-types": "^15.6.0"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------