felix-cao / Blog

A little progress a day makes you a big success!
29 stars 4 forks source link

基于 React 和 GSAP 实现数字动画 #195

Open felix-cao opened 3 years ago

felix-cao commented 3 years ago

chrome-capture

如上图,integer 整数和 float 是有滚动动画的,我喜欢用最少,最简洁的代码实现功能,这个 component 比较轻,所以使用了 React 16.8 增加的 Hooks Feature,直接上代码:

一、整数动画

import gsap from 'gsap';
import React, { useState } from 'react';
const XintegerByNumber = (props: any) => {
  const [stats, setStats] = useState({ value: 0 })
  let gsapId: any;
  useEffect(() => {
    const target = { value: stats.value };
    gsapId = gsap.to(target, {
      duration: 3,
      ease: "none",
      value: props.value,
      roundProps: "value",
      onUpdate: () => setStats({ value: target.value }),
    });
    return () => gsapId && gsapId.kill();
  }, []);

  return (
    <div style={{...props.style, display: 'inline'}}>
      <span>{stats.value}</span>
      {props.children}
    </div>
  );
};

二、浮点数动画

import * as _ from 'lodash';
import gsap, { Linear, TweenMax } from 'gsap';
import React, { useState, useEffect, useRef } from 'react';
const XfloaterByText = (props: any) => {
  const decimal = props.decimal || 2;
  const span: any = useRef<HTMLDivElement>(null);
  useEffect(() => {
    const target = { value: 0 };
    TweenMax.to(target, 3, {
      value: props.value, 
      ease: Linear.easeNone, 
      onUpdate: () => _.set(span.current, 'innerHTML', target.value.toFixed(decimal)),
    });
  }, [])

  return (
    <div style={{...props.style, display: 'inline'}}>
      <span ref={span}>0</span>
      {props.children}
    </div>
  );
};