react + ant-design实现数字对比动画效果:当新获取的数字比之前展示的数字多或少2时,显示“+2”或“-2”的动画效果

发布于:2025-06-28 ⋅ 阅读:(14) ⋅ 点赞:(0)

 react + ant-design实现数字对比动画效果:当新获取的数字比之前展示的数字多或少2时,显示“+2”或“-2”的动画效果

1. 创建独立的 AnimatedValue 组件

// components/AnimatedValue/index.jsx
import React, { useState, useEffect, useRef } from 'react';
import styles from './styles.module.less';

const AnimatedValue = ({ value, name }) => {
  const [displayValue, setDisplayValue] = useState('--');
  const [diff, setDiff] = useState(null);
  const prevValue = useRef(null);
  const isInitialLoad = useRef(true);

  useEffect(() => {
    if (value !== undefined && value !== null) {
      const numValue = Number(value);
      
      // 只有在不是初始加载且前值存在时才计算差值
      if (!isInitialLoad.current && prevValue.current !== null) {
        const difference = numValue - prevValue.current;
        if (Math.abs(difference) >= 1) {
          setDiff(difference);
          // 3秒后清除差值显示
          const timer = setTimeout(() => setDiff(null), 3000);
          return () => clearTimeout(timer);
        }
      }
      
      prevValue.current = numValue;
      setDisplayValue(numValue);
      
      if (isInitialLoad.current) {
        isInitialLoad.current = false;
      }
    } else {
      setDisplayValue('--');
    }
  }, [value]);

  return (
    <div className={styles.value_container}>
      <div className={styles.value}>{displayValue}</div>
      {diff !== null && (
        <div className={`${styles.diff_animation} ${
          diff > 0 ? styles.increase : styles.decrease
        }`}>
          {diff > 0 ? `+${diff}` : diff}
        </div>
      )}
    </div>
  );
};

export default AnimatedValue;

2. 对应的样式文件

// components/AnimatedValue/styles.module.less
.value_container {
  position: relative;
  display: inline-block;
  min-width: 60px;
  height: 30px; // 固定高度防止布局抖动
}

.value {
  display: inline-block;
}

.diff_animation {
  position: absolute;
  right: -30px;
  top: 0;
  font-size: 14px;
  font-weight: bold;
  animation: fadeUp 1.5s ease-out forwards;
  will-change: transform, opacity;
  
  &.increase {
    color: #f5222d; // 红色表示增加
  }
  
  &.decrease {
    color: #52c41a; // 绿色表示减少
  }
}

@keyframes fadeUp {
  0% {
    opacity: 1;
    transform: translateY(0);
  }
  70% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    transform: translateY(-20px);
  }
}

3. 在父组件中使用

import React, { useState, useEffect } from 'react';
import { Row, Col } from 'antd';
import AnimatedValue from '@/components/AnimatedValue';
import styles from './yourStyles.module.less';

const BusiMonitor = () => {
    const [data, setData] = useState([]);

    // 模拟API调用
    const fetchData = () => {
        // 模拟数据变化
        const newData = data.map(item => ({
            ...item,
            value: Math.floor(Math.random() * 20)
        }));
        setData(newData);
    };

    // 设置定时器,每10秒调用一次API
    useEffect(() => {
        const timer = setInterval(fetchData, 10000);
        fetchData(); // 初始加载数据
        return () => clearInterval(timer);
    }, []);

    return (
        <Row justify="space-between">
            {data.map(({ name, value }, index) => (
                <Col >
                    <div>
                        <div className={styles.name}>{name}业务量</div>
                        <AnimatedValue value={value} name={name} />
                    </div>
                </Col>
            ))}
        </Row>
    );
};

export default BusiMonitor;


网站公告

今日签到

点亮在社区的每一天
去签到