简体   繁体   中英

How to create an animated counter in React.js?

I'm looking for a way to animate a counter in React.

For the sake of the example, I have 3 components of the following structure:

  • Master:
    • logicComponent
    • Counter

(Master is the parent of logicComponent and Counter)

The logic component passes a number to the master who passes it to the Counter component that should do the animation. The logicComponent sends the numbers in an incremental manner, that is, each time that something happens there, it sends an update.

For example, the logicCounter invokes the Master ten times to increment the counter, I would've expected that the Counter will be rendered 10 times showing 10 numbers. All the things I've tried so far resulted in showing the final number (10) without any incrementation.

After looking for solutions, I came across Window.requestAnimationFrame() and I'm looking for a proper way to implement it in React.

I'm trying to avoid 3rd party npms/libraries.

Would love your help / ideas. Thanks.

For an animated counter in React-JS, I use 'react-count' : A configurable React component wrapper around 'CountUp.js'.

Please Refer : https://github.com/glennreyes/react-countup . Check out live demo : https://glennreyes.github.io/react-countup/ Steps :

Install :

*npm install react-countup --save*
or
*yarn add react-countup*

Simple Example :

import React from 'react';
import { render } from 'react-dom';
import CountUp from 'react-countup';

render(
  <CountUp start={0} end={160526} />,
  document.getElementById('root')
);

Advanced Example :

import React from 'react';
import { render } from 'react-dom';
import CountUp from 'react-countup';

const onComplete = () => {
  console.log('Completed!');
};

const onStart = () => {
  console.log('Started!');
};

render(
  <CountUp
    className="account-balance"
    start={160527.0127}
    end={-875.0319}
    duration={2.75}
    useEasing={true}
    useGrouping={true}
    separator=" "
    decimals={4}
    decimal=","
    prefix="EUR "
    suffix=" left"
    onComplete={onComplete}
    onStart={onStart}
  />,
  document.getElementById('root'),
);

maybe you should try my package, if you are using react.

在此输入图像描述

https://github.com/bluebill1049/react-flip-numbers

i have used it to create the above count down timer.

code example below:

import react from 'react';
import FlipNumbers from 'react-flip-numbers';

export default function SexyComponent(props) {
    return <div>
        <FlipNumbers
            height="12px"
            width="12px"
            color="red"
            background="white"
            startAnimation
            numbers="12345"
            numberStyle={{ color: "black" }}
      />
    </div>;
}

window.requestAnimationFrame() is mostly for animation optimization on browser. Your can read more about it here: http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/

But I don't think it could help you with your issue. From what I understand your problem is with your react components.

Here is an example of a possible implementation of your architecture: https://jsfiddle.net/snahedis/69z2wepo/28572/

var Master = React.createClass({
  increment: function() {
    this.refs.counter.increment();
  },
  render: function() {
    return (
      <div>
        <Counter ref="counter" />
        <Logic increment={this.increment} />
      </div>
    );
  }
});

var Logic = React.createClass({
  render: function() {
    return <button onClick={this.props.increment}>increment</button>;
  }
});

var Counter = React.createClass({
  getInitialState: function() {
    return {
        counter: 0
    };
  },
  increment: function() {
    this.setState({
        counter: this.state.counter + 1
    });
  },
  render: function() {
    return <div>{this.state.counter}</div>;
  }
});

ReactDOM.render(
  <Master />,
  document.getElementById('container')
);

Obviously the increment method on the Logic component could be triggered with something else that a click on a button.

However, this structure is a bit strange. If it's possible I would recommend to change it. Logic component would become the parent of the Counter component rather than his sibling.

Here is the example: https://jsfiddle.net/snahedis/69z2wepo/28573/

var Master = React.createClass({
  render: function() {
    return (
      <div>
        <CounterLogicWrapper />
      </div>
    );
  }
});

var CounterLogicWrapper = React.createClass({
  getInitialState: function() {
    return {
        counter: 0
    };
  },
  increment: function() {
    this.setState({
        counter: this.state.counter + 1
    });
  },  
  render: function() {
    return (
      <div>
        <Counter counter={this.state.counter} />
        <button onClick={this.increment}>increment</button>
      </div>
    );
  }
});

var Counter = React.createClass({
  render: function() {
    return <div>{this.props.counter}</div>;
  }
});

ReactDOM.render(
  <Master />,
  document.getElementById('container')
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM