使用Styled Components改变SVG描边的颜色

12

我有一个SVG,我正在使用作为<img>标签。我正在尝试使用Styled Components将其改为在悬停时更改描边颜色。

我导入了SVG:

import BurgerOpenSvg from '../../images/burger_open.svg';

我为此创建了一个Styled Components:

   const BurgerImageStyle = styled.img`
    &:hover {     
        .st0 {
          stroke: red;
        }
    }
`;

我使用它:

<BurgerImageStyle alt="my-burger" src={BurgerOpenSvg}/>     

结果是,我的SVG被正确显示,但悬停时没有颜色更改
我使用的SVG来源:
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" 
     viewBox="0 0 38 28.4" style="enable-background:new 0 0 38 28.4;" xml:space="preserve">
<style type="text/css">
    .st0{fill:none;stroke:#221f1f;stroke-width:2;stroke-miterlimit:10;}
</style>
<g>
    <g id="XMLID_7_">
        <line class="st0" x1="0" y1="1" x2="38" y2="1"/>
    </g>
    <g id="XMLID_6_">
        <line class="st0" x1="0" y1="14.2" x2="38" y2="14.2"/>
    </g>
    <g id="XMLID_5_">
        <line class="st0" x1="0" y1="27.4" x2="38" y2="27.4"/>
    </g>
</g>
</svg>

SVG 渲染如下:

enter image description here

在一个 <img> 标签中加载的 SVG 是否可以更新类名?还是必须使用内联的 <svg> 标签?


你在浏览器中看到悬停样式了吗? - isherwood
.NYIBr:hover .st0{stroke:red;} -- 但没有效果。 - JasonGenX
那么问题不在于React,而是在于你的CSS。该元素是否有该类? - isherwood
st0 是用于在 SVG 中呈现三条线的类。 - JasonGenX
我指的是.NYIBr。那是操作类。 - isherwood
显示剩余2条评论
4个回答

11

所以我调查了一下。结果发现你不能使用<img>标签加载的SVG图像进行CSS样式设置。

我做的是这样的:

我将我的SVG内联到HTML中,像这样:

 <BurgerImageStyle x="0px" y="0px" viewBox="0 0 38 28.4">
      <line x1="0" y1="1" x2="38" y2="1"/>
      <line x1="0" y1="14.2" x2="38" y2="14.2"/>
      <line x1="0" y1="27.4" x2="38" y2="27.4"/>
 </BurgerImageStyle>

然后我使用Styled Components来为BurgerImageStyle添加样式:

const BurgerImageStyle = styled.svg`
    line {
      stroke: black;
    }    
    &:hover {
      line {
        stroke: purple;
      }
    }     
`;

这起作用了。


11
如果您想避免编写单独的组件或复制原始SVG文件,请考虑使用react-inlinesvg

https://github.com/gilbarbara/react-inlinesvg

import React from "react";
import styled from "styled-components";
import SVG from "react-inlinesvg";
import radio from "./radio.svg";

interface SVGProps {
  color: string;
}

const StyledSVG = styled(SVG)<SVGProps>`
  width: 24px;
  height: 24px;
  & path {
    fill: ${({ color }) => color};
  }
`;

export default function App() {
  const color = "#007bff";
  return <StyledSVG color={color} src={radio} />;
}

代码沙盒: https://codesandbox.io/s/stack-56692784-styling-svgs-iz3dc?file=/src/App.tsx:0-414


1
如果你想让多个SVG共享一些样式,并且不想增加对react-inlinesvg的依赖,你可以使用以下方式代替:
src属性中,它接受SVG React组件。
import styled from 'styled-components';
import React, { FC, memo } from 'react';

type StyledIconProps = {
  checked?: boolean;
};

const StyledIconWrapper = styled.div<StyledIconProps>`
  & svg {
    color: ${(p) => p.checked ? '#8761DB' : '#A1AAB9'};
    transition: 0.1s color ease-out;
  }
`;

export const StyledIcon = memo((props: StyledIconProps & { src: FC }) => {
  const { src, ...rest } = props;

  const Icon = src;

  return (
    <StyledIconWrapper {...rest}>
      <Icon/>
    </StyledIconWrapper>
  );
});

然后您可以像这样使用它:

import { StyledIcon } from 'src/StyledIcon';
import { ReactComponent as Icon } from 'assets/icon.svg';

const A = () => (<StyledIcon src={Icon} checked={false} />)

0
除了JasonGenX所提到的内容外,我还建议在使用SVG组件(例如使用SVGR生成的组件)时考虑以下情况。这甚至在styled-components文档中都有提到,并且与其API结合使用可以无缝解决它。
首先导入您的图标。
import React from 'react';
import styled from 'styled-components';
import YourIcon from '../../icons/YourIcon';

在我的情况下,我添加了一个带有样式的按钮,像这样:
const StyledButton = styled.button`
  ...
`;

// Provide a styled component from YourIcon
// You can also change the line for path and stroke for fill for instance
const StyledIcon = styled(YourIcon)`
  ${StyledButton}:hover & line {
    stroke: #db632e;
  }
`;

const YourButton = () => {
  return (
    <StyledButton>
      <StyledIcon /> Click me
    </StyledButton>
  );
};

export default YourButton;

之后,你会看到你的图标改变颜色。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接