The code powering m.abunchtell.com https://m.abunchtell.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

66 lines
1.7 KiB

  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import { FormattedNumber } from 'react-intl';
  4. import TransitionMotion from 'react-motion/lib/TransitionMotion';
  5. import spring from 'react-motion/lib/spring';
  6. import { reduceMotion } from 'mastodon/initial_state';
  7. export default class AnimatedNumber extends React.PureComponent {
  8. static propTypes = {
  9. value: PropTypes.number.isRequired,
  10. };
  11. state = {
  12. direction: 1,
  13. };
  14. componentWillReceiveProps (nextProps) {
  15. if (nextProps.value > this.props.value) {
  16. this.setState({ direction: 1 });
  17. } else if (nextProps.value < this.props.value) {
  18. this.setState({ direction: -1 });
  19. }
  20. }
  21. willEnter = () => {
  22. const { direction } = this.state;
  23. return { y: -1 * direction };
  24. }
  25. willLeave = () => {
  26. const { direction } = this.state;
  27. return { y: spring(1 * direction, { damping: 35, stiffness: 400 }) };
  28. }
  29. render () {
  30. const { value } = this.props;
  31. const { direction } = this.state;
  32. if (reduceMotion) {
  33. return <FormattedNumber value={value} />;
  34. }
  35. const styles = [{
  36. key: `${value}`,
  37. data: value,
  38. style: { y: spring(0, { damping: 35, stiffness: 400 }) },
  39. }];
  40. return (
  41. <TransitionMotion styles={styles} willEnter={this.willEnter} willLeave={this.willLeave}>
  42. {items => (
  43. <span className='animated-number'>
  44. {items.map(({ key, data, style }) => (
  45. <span key={key} style={{ position: (direction * style.y) > 0 ? 'absolute' : 'static', transform: `translateY(${style.y * 100}%)` }}><FormattedNumber value={data} /></span>
  46. ))}
  47. </span>
  48. )}
  49. </TransitionMotion>
  50. );
  51. }
  52. }