By Kevin Hou
2 minute read
I found a really cool way of making a number counter engaging. A co-worker at Salesforce, named Amy Lee, created a simple React component designed to mimic a slot machine. Instead of simply changing the number, the function "animates" the change and rolls up to that number. The cool thing about this is that it works for any number and it requires no CSS3 animation. It looks neat, especially with huge numbers!
Usage:
1<!-- The total time will be 300ms with one frame every 20ms. --> 2<AnimatedNumber number="{this.state.number}" time="{300}" frameRate="{20}" /> 3
Component source:
1const AnimatedNumber = React.createClass({
2 getInitialState() {
3 return {
4 number: this.props.number,
5 };
6 },
7 componentWillReceiveProps(props) {
8 if (this.state.number !== props.number) {
9 // If different number
10 if (this._interval) {
11 //If theres an interval
12 clearInterval(this._interval); // Clear the existing interval
13 }
14 let framesLeft = this.props.time / this.props.frameRate; //Determine frame rate
15 let increment = (props.number - this.state.number) / (framesLeft + 1); //Determine increment per frame
16 this._interval = setInterval(() => {
17 if (framesLeft > 0) {
18 //If there are frames
19 this.setState({ number: this.state.number + increment }); //Set new number
20 framesLeft--; //Subtract a frame
21 } else {
22 //If done
23 clearInterval(this._interval); //Clear the interval
24 this._interval = null; //Set to null
25 this.setState({ number: props.number }); //Set the final value to the exact value just in case
26 }
27 }, this.props.frameRate); //How often it repeats
28 }
29 },
30 render() {
31 return (
32 <span>
33 {Math.round(this.state.number)} //Round if you don't want a decimal
34 </span>
35 );
36 },
37});
38