You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React项目中实现Ant Design官网同款主题切换动画?

实现Ant Design官网式主题切换圆形扩散动画

核心思路

这个效果的核心是做一个跟随点击位置的圆形遮罩层,通过CSS动画让它从按钮中心扩散至全屏,同时同步切换页面主题样式,动画结束后隐藏遮罩即可。

具体实现步骤

1. 编写React组件逻辑

在组件中添加遮罩元素的状态管理,处理点击时的坐标计算和动画触发:

import { useState } from 'react';

function ThemeToggle() {
  const [currentTheme, setCurrentTheme] = useState('light');
  const [maskStyle, setMaskStyle] = useState(null);

  const toggleTheme = (e) => {
    // 获取切换按钮的实时位置和尺寸
    const btnRect = e.currentTarget.getBoundingClientRect();
    const centerX = btnRect.left + btnRect.width / 2;
    const centerY = btnRect.top + btnRect.height / 2;

    // 设置遮罩初始状态:定位在按钮中心,尺寸为0
    setMaskStyle({
      left: `${centerX}px`,
      top: `${centerY}px`,
      width: '0px',
      height: '0px',
      backgroundColor: currentTheme === 'light' ? '#1a1a1a' : '#ffffff',
      display: 'block'
    });

    // 延迟切换主题,让遮罩动画先启动
    setTimeout(() => {
      setCurrentTheme(prev => prev === 'light' ? 'dark' : 'light');
    }, 50);

    // 动画结束后隐藏遮罩
    setTimeout(() => {
      setMaskStyle(null);
    }, 600);
  };

  return (
    <div className={`app-wrapper ${currentTheme}`}>
      {/* 主题切换按钮 */}
      <button className="theme-switch-btn" onClick={toggleTheme}>
        切换主题
      </button>

      {/* 动画遮罩层 */}
      {maskStyle && (
        <div 
          className="theme-transition-mask"
          style={maskStyle}
        />
      )}
    </div>
  );
}

export default ThemeToggle;

2. 配置CSS动画样式

为遮罩层添加关键帧动画,实现从点到面的扩散效果:

.app-wrapper {
  width: 100vw;
  height: 100vh;
  transition: background-color 0.3s;
}

.app-wrapper.light {
  background-color: #fff;
  color: #1a1a1a;
}

.app-wrapper.dark {
  background-color: #1a1a1a;
  color: #fff;
}

.theme-switch-btn {
  position: fixed;
  bottom: 20px;
  right: 20px;
  padding: 10px 16px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.theme-transition-mask {
  position: fixed;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  z-index: 9999;
  animation: expandToFullScreen 0.5s forwards;
  pointer-events: none; /* 避免遮罩阻挡页面交互 */
}

@keyframes expandToFullScreen {
  to {
    width: 200vw;
    height: 200vw; /* 用vw确保覆盖全屏,适配不同屏幕尺寸 */
  }
}

3. 关键细节注意

  • 坐标计算:用getBoundingClientRect()获取按钮的实时位置,确保遮罩从按钮中心准确扩散。
  • 动画与主题切换时机:延迟50ms切换主题,让遮罩动画先启动,视觉过渡更自然。
  • 遮罩尺寸:设置200vw的宽高,确保无论页面宽度如何,都能完全覆盖屏幕,避免留白。
  • 层级控制:遮罩层设置高z-index,保证在所有页面内容上方显示。

适配Ant Design主题变量

如果你的项目用Ant Design定制主题,可以把遮罩背景色替换为对应的主题变量,比如:

// 假设项目使用CSS变量或Less变量
backgroundColor: currentTheme === 'light' ? '--ant-color-bg-dark' : '--ant-color-bg'

内容的提问来源于stack exchange,提问作者Amaranthus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 09:55:05