css 在React中悬停时更改svg笔划

2w2cym1i  于 2023-06-25  发布在  React
关注(0)|答案(3)|浏览(134)

在我的React项目中,我想在悬停时更改svg的stroke-color。我通过将svg导入为ReactCompnent,然后有条件地发送prop(使用State钩子来确定它是否被悬停)来实现这一点。但我想知道是否有其他简单的方法来解决这个问题?因为,如果对多个svg图标执行此操作,代码将变得冗长。代码如下:

import { useState } from "react";
import { render } from "react-dom";
import "./index.css";
import { ReactComponent as Icon_5 } from "./icon_5.svg";

function App() {
  const [isHovered, setIsHovered] = useState(false);

  const handleMouseEnter = () => {
    setIsHovered(true);
  };

  const handleMouseLeave = () => {
    setIsHovered(false);
  };
  return (
    <>
      <div>
        <h1>Using with prop</h1>
        <Icon_5
          className="icon"
          stroke={isHovered ? "#FF0000" : "#00ade9"}
          onMouseEnter={handleMouseEnter}
          onMouseLeave={handleMouseLeave}
        />
      </div>
    </>
  );
}

render(<App />, document.getElementById("root"));

我也试过通过css应用颜色,但问题是,每个svg都有不同的结构。例如,为了完全改变这个图标的笔画,我不得不这样给予它css:

.icon_1 path {
  stroke: green;
}

.icon_1 line {
  stroke: green;
}

.icon_1 rect {
  stroke: green;
}

这对于每个svg图标都是不同的。所以,这种方法似乎不适合这种情况。
下面是代码和框的例子:https://codesandbox.io/s/svgfill-3-w7kl7n?file=/index.js:0-684

8ulbf1ek

8ulbf1ek1#

只需给予svg组件的父组件一个id或class,并从所有svg中删除props和stroke。在CSS中,你可以用途:

index.css:

.svg-container svg {
  stroke: gray;
}
.svg-container svg:hover {
  stroke: red;
}

/* svg#icon-5 {
  stroke: gray;
}

svg#icon-5:hover {
  stroke: red;
} */

App.js:

import "./index.css";
import { ReactComponent as Icon5 } from "./icon_5.svg";

function App() {
  return (
    <>
      <div class="svg-container">
        <Icon5 />
      </div>
    </>
  );
}

icon_5.svg:

<svg xmlns="http://www.w3.org/2000/svg" id="icon-5" width="27.802" height="24.704" viewBox="0 0 27.802 24.704">
  <g id="icon_calendar-clock" transform="translate(0.75 0.75)">
    <g id="Group_2511" data-name="Group 2511" transform="translate(-1 -1)">
      <g id="Group_15380" data-name="Group 15380">
        <line id="Line_297" data-name="Line 297" y2="4.013" transform="translate(6.744 1)" fill="none"  stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
        <line id="Line_298" data-name="Line 298" y2="4.013" transform="translate(16.685 1)" fill="none"   stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
        <line id="Line_299" data-name="Line 299" x2="20.857" transform="translate(1 9.025)" fill="none"   stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
      </g>
    </g>
    <rect id="Rectangle_3594" data-name="Rectangle 3594" width="3.017" height="3.017" transform="translate(3.57 11.395)" fill="none"   stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
    <rect id="Rectangle_3595" data-name="Rectangle 3595" width="3.017" height="3.017" transform="translate(9.33 11.395)" fill="none"   stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
    <g id="Group_2513" data-name="Group 2513" transform="translate(-1 -1)">
      <g id="Group_2527" data-name="Group 2527">
        <path id="Path_7197" data-name="Path 7197" d="M15.908,18.506a5.7,5.7,0,0,1,5.7-5.7,5.8,5.8,0,0,1,.739.053V5.943a2.756,2.756,0,0,0-2.756-2.756H3.756A2.756,2.756,0,0,0,1,5.943V19.585a2.755,2.755,0,0,0,2.756,2.756H17.4A5.67,5.67,0,0,1,15.908,18.506Z" fill="none"   stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
        <path id="Path_7199" data-name="Path 7199" d="M21.6,12.809a5.7,5.7,0,1,1-5.7,5.7A5.7,5.7,0,0,1,21.6,12.809Z" fill="none"   stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
        <path id="Path_7200" data-name="Path 7200" d="M23.753,19.369h-2.7v-3.1" fill="none"   stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
      </g>
    </g>
  </g>
</svg>

你也可以给予每个svg标签(在svg文件中)一个单独的id,并使用它来样式化。即使你使用svg作为react组件,它也会在最后呈现为纯svg,并将css应用于最终结果,因此你可以像访问常规svg标签一样访问它。我建议你从svg中的所有地方删除stroke,如果图标的所有子部分(path,rect等)都是单一颜色的话。否则,你可能会在svgs上使用外部和内部样式时遇到问题。也不要像这样直接使用render(),用途:ReactDOM.createRoot()

ql3eal8s

ql3eal8s2#

您可以通过在React中创建可重用组件来实现在悬停时更改SVG的笔触颜色的所需行为。下面是一个例子:

import React, { useState } from "react";
import { ReactComponent as Icon_5 } from "./icon_5.svg";

function HoverableIcon({ defaultColor, hoverColor, ...restProps }) {
  const [isHovered, setIsHovered] = useState(false);

  const handleMouseEnter = () => {
    setIsHovered(true);
  };

  const handleMouseLeave = () => {
    setIsHovered(false);
  };

  return (
    <Icon_5
      {...restProps}
      stroke={isHovered ? hoverColor : defaultColor}
      onMouseEnter={handleMouseEnter}
      onMouseLeave={handleMouseLeave}
    />
  );
}

function App() {
  return (
    <div>
      <h1>Using with prop</h1>
      <HoverableIcon
        className="icon"
        defaultColor="#00ade9"
        hoverColor="#FF0000"
      />
    </div>
  );
}

export default App;

在本例中,HoverableIcon组件负责处理悬停行为和颜色更改。它需要两个 prop :defaultColor和hoverColor,它们允许您指定默认描边颜色和悬停时应用的颜色。
在HoverableIcon组件中,我们使用useState钩子来管理悬停状态(isHovered)。在mouseenter上,isHovered状态被设置为true,在mouseleave上,它被设置回false。SVG的笔划颜色是基于isHovered状态来确定的。
要使用HoverableIcon组件,只需将其导入到主应用程序组件(例如App)中,并使用所需的默认颜色和悬停颜色呈现它。
这种方法允许您为多个SVG图标重用HoverableIcon组件,从而减少代码重复,并保持代码的整洁和可维护性。
您可以随意定制HoverableIcon组件以满足您的特定需求,并将其用于项目中的任意数量的SVG图标。

vatpfxk5

vatpfxk53#

使用CSS :hover有什么问题?
它与SVG元素一起工作。

<>
      <div>
        <h1>Using with prop</h1>
        <Icon_5 className="icon icon-5" />
      </div>
    </>
svg.icon-5 { stroke: #00ade9; }
svg.icon-5:hover { stroke: #FF0000; }

除非我错过了什么
链接到沙盒here

相关问题