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

React中如何根据状态动态切换SVG图标颜色?

实现SidemenuItem组件SVG图标根据状态切换颜色的方案

你需要实现SidemenuItem组件根据variant的active/default状态切换传入SVG图标的颜色,以下是几种可行的实现方案:

方案一:使用currentColor(推荐)

这是最简洁且易于维护的方案,利用CSS的currentColor属性让SVG继承父元素的文字颜色,再通过组件的状态类切换颜色。

步骤1:修改传入的SVG代码

将SVG中所有固定的fill="#xxx"替换为fill="currentColor",这样SVG的颜色会自动继承父元素的color属性:

// 修改后的DashBoard SVG示例
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path opacity="0.5" d="M26.1039 11H16.8961..." fill="currentColor" />
    <path d="M26.1039 3H16.8961..." fill="currentColor" />
    <path d="M13.1035 17H3.8965..." fill="currentColor" />
    <path opacity="0.5" d="M13.1035 3.00001H3.8965..." fill="currentColor" />
</svg>

步骤2:修改SidemenuItem组件

在包裹图标的span元素中,根据variant状态添加对应的颜色类:

export function SidemenuItem({
    text = 'Menu Item',
    icon,
    disabled = false,
    children,
    variant = 'default',
    onClick
}: MenuItemProps) {
    const handleClick: MouseEventHandler<HTMLDivElement> = (event) => {
        if (!disabled && onClick) {
            onClick(event);
        }
    };

    return (
        <div 
            onClick={handleClick} 
            className={`flex items-center ${variant !== "active" ? 'gap-3' : 'gap-5'} menu-item ${disabled ? 'cursor-not-allowed opacity-50' : ''}`}
        >
            {/* 添加颜色类:active状态用text-primary-normal,默认状态用你需要的颜色类,比如text-gray-600 */}
            <span className={`menu-icon flex flex-col items-end h-12 w-1/3 rounded-r-full p-3 ${variant === "active" ? 'bg-purple-20 text-primary-normal' : 'text-gray-600'}`}>
                {icon}
            </span>
            <p className={`menu-text ${variant === "active" ? 'text-primary-normal ml-3' : ''} font-semibold`}>{text}</p>
            {children}
        </div>
    );
}

方案二:通过React.cloneElement动态修改SVG属性

如果无法修改传入的SVG代码,可以使用React.cloneElement克隆图标元素,动态设置fill属性:

import { MouseEventHandler, ReactNode, cloneElement } from 'react';

export function SidemenuItem({
    text = 'Menu Item',
    icon,
    disabled = false,
    children,
    variant = 'default',
    onClick
}: MenuItemProps) {
    const handleClick: MouseEventHandler<HTMLDivElement> = (event) => {
        if (!disabled && onClick) {
            onClick(event);
        }
    };

    // 处理图标颜色
    const getColoredIcon = () => {
        const iconColor = variant === 'active' ? '#4C2BBF' : '#322E3D'; // 根据你的需求定义颜色
        if (React.isValidElement(icon)) {
            // 克隆SVG元素,设置fill属性
            return cloneElement(icon, {
                style: { ...icon.props.style, fill: iconColor },
                // 如果SVG内部有path,还可以递归处理子元素,这里简化处理
            });
        }
        // 处理多个图标的情况
        if (Array.isArray(icon)) {
            return icon.map((item, index) => 
                React.isValidElement(item) ? cloneElement(item, { style: { ...item.props.style, fill: iconColor }, key: index }) : item
            );
        }
        return icon;
    };

    return (
        <div 
            onClick={handleClick} 
            className={`flex items-center ${variant !== "active" ? 'gap-3' : 'gap-5'} menu-item ${disabled ? 'cursor-not-allowed opacity-50' : ''}`}
        >
            <span className={`menu-icon flex flex-col items-end h-12 w-1/3 rounded-r-full p-3 ${variant === "active" ? 'bg-purple-20' : ''}`}>
                {getColoredIcon()}
            </span>
            <p className={`menu-text ${variant === "active" ? 'text-primary-normal ml-3' : ''} font-semibold`}>{text}</p>
            {children}
        </div>
    );
}

注意:如果SVG内部有多个带独立fill的path,需要递归遍历子元素修改每个path的fill属性,这个方案相对复杂,适合无法修改SVG源文件的场景。

方案三:使用CSS滤镜(备选)

如果不想修改SVG或组件逻辑,可以用CSS的filter属性快速调整颜色,不过颜色控制不够精准:

/* 在你的CSS文件中添加 */
.menu-icon.active svg {
    filter: hue-rotate(180deg) brightness(1.2); /* 根据需求调整滤镜参数 */
}
.menu-icon.default svg {
    filter: grayscale(50%);
}

然后在组件中给menu-icon添加对应的类:

<span className={`menu-icon flex flex-col items-end h-12 w-1/3 rounded-r-full p-3 ${variant === "active" ? 'bg-purple-20 active' : 'default'}`}>
    {icon}
</span>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 21:09:51