首页 > 解决方案 > 在 Header 中隐藏带有 linearGradient 的 react svg 组件也将 svg 隐藏在 Header 之外

问题描述

我有一个带有 linearGradient 的 svg react 组件,它在我的 Header 组件和我的主要组件中呈现。当我display: none为 Header 组件设置样式时,我希望 Header 组件中的 svg 是隐藏的,而主组件中的 svg 是可见的。当我使用没有linearGradient的svg时,我得到了隐藏在Header中并在主组件中可见的svg的预期行为。但是,如果 svg 使用 linearGradient,则设置display: none为 Header 会隐藏 Header 和主组件中的 svg。

为了重现这个问题,我有 2 个反应组件PythonIcon(使用线性渐变)和WebpackIcon(不使用线性渐变)。在我的 Header 中,我渲染了 Header并App.js同时渲染了我的主要组件:PythonIconWebpackIcon

import React from "react";
import Header from "./Header";
import PythonIcon from "./PythonIcon";
import WebpackIcon from "./WebpackIcon";

function App() {
  return (
    <div>
      <Header />
      <main style={{ marginTop: "1rem", border: "1px solid green" }}>
        <h1>
          <PythonIcon width="20" height="20" />
          Python
        </h1>
        <h1>
          <WebpackIcon width="20" height="20" />
          Webpack
        </h1>
      </main>
    </div>
  );
}

export default App;

在我的 Header 组件中,我还渲染PythonIconWebpackIcon

import React from "react";
import PythonIcon from "./PythonIcon";
import WebpackIcon from "./WebpackIcon";

export default function Header() {
  return (
    <header style={{ border: "1px solid red", display: "block" }}>
      <h1>
        <PythonIcon width="20" height="20" />
        Python
      </h1>
      <h1>
        <WebpackIcon width="20" height="20" />
        Webpack
      </h1>
    </header>
  );
}

页面如下所示:

一个

但是一旦我在 Header 组件中更改display: blockdisplay: none,页面将如下所示:

b

请注意,webpack 图标(不使用 linearGradient)在主组件中正确显示,但 python 图标(使用 linearGradient)没有。

这是出乎意料的。难道我做错了什么?有没有办法隐藏标题中的python图标而不隐藏主要组件中的python图标?我正在尝试使用 css media-query 创建一个响应式导航栏来显示/隐藏导航栏。不幸的是,隐藏带有 svg 图标的导航栏也会在我渲染的其他组件中隐藏 svg 图标。

我在https://github.com/kimbaudi/react-svg-lineargradient-issue提供了一个最小的复制品

标签: reactjssvg

解决方案


所以我找到了解决这个问题的方法。发生这种情况的原因是因为使用 linearGradient 或 RadialGradient 的 svg 包含ids,并且当您在页面中渲染多个 svg 时,会导致奇怪的事情发生,因为 DOM 期望有一个唯一的 id。

所以我之前的PythonIconreact svg 组件已经硬编码了ids 并且看起来像这样:

import React from "react";

const PythonIcon = (props) => (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    viewBox="0 0 64 64"
    width="64"
    height="64"
    {...props}
  >
    <linearGradient
      id="pythonLinearGradient1"
      x1="611.11"
      x2="720.13"
      y1="-280.51"
      y2="-374.3"
      gradientTransform="matrix(.32049 0 0 -.32362 -197.36 -88.951)"
      gradientUnits="userSpaceOnUse"
    >
      <stop stopColor="#5A9FD4" offset="0" />
      <stop stopColor="#306998" offset="1" />
    </linearGradient>
    <path
      fill="url(#pythonLinearGradient1)"
      strokeWidth=".56976"
      d="m31.344 0c-2.6209 0-5.1278 0.2279-7.2929 0.62674-6.4383 1.1395-7.6348 3.5325-7.6348 7.9197v5.8116h15.27v1.9372h-21.024c-4.4441 0-8.3185 2.6779-9.572 7.7488-1.4244 5.8116-1.4814 9.458 0 15.498 1.0825 4.5011 3.7034 7.7488 8.1476 7.7488h5.2418v-6.9511c0-5.0139 4.3872-9.515 9.572-9.515h15.27c4.2732 0 7.6348-3.4755 7.6348-7.7488v-14.529c0-4.1593-3.4755-7.236-7.6348-7.9197-2.6209-0.45581-5.3558-0.62674-7.9767-0.62674zm-8.2615 4.672c1.5953 0 2.8488 1.3104 2.8488 2.9058 0 1.5953-1.3104 2.9058-2.8488 2.9058-1.5953 0-2.8488-1.3104-2.8488-2.9058 0-1.5953 1.2535-2.9058 2.8488-2.9058z"
    />
    <linearGradient
      id="pythonLinearGradient2"
      x1="762.27"
      x2="723.34"
      y1="-431.07"
      y2="-375.99"
      gradientTransform="matrix(.32049 0 0 -.32362 -197.36 -88.951)"
      gradientUnits="userSpaceOnUse"
    >
      <stop stopColor="#FFD43B" offset="0" />
      <stop stopColor="#FFE873" offset="1" />
    </linearGradient>
    <path
      fill="url(#pythonLinearGradient2)"
      strokeWidth=".56976"
      d="m48.836 16.352v6.7802c0 5.2418-4.4441 9.6859-9.572 9.6859h-15.213c-4.1593 0-7.6348 3.5895-7.6348 7.7488v14.529c0 4.1593 3.5895 6.5523 7.6348 7.7488 4.843 1.4244 9.458 1.6523 15.27 0 3.8744-1.1395 7.6348-3.3616 7.6348-7.7488v-5.8116h-15.27v-1.9372h22.904c4.4441 0 6.0964-3.0767 7.6348-7.7488 1.5953-4.786 1.5384-9.4011 0-15.498-1.0825-4.4441-3.1907-7.7488-7.6348-7.7488zm-8.5464 36.807c1.5953 0 2.8488 1.3104 2.8488 2.9058 0 1.5953-1.3104 2.9058-2.8488 2.9058-1.5953 0-2.8488-1.3105-2.8488-2.9058-0.05698-1.5953 1.2535-2.9058 2.8488-2.9058z"
    />
  </svg>
);

export default PythonIcon;

现在我将一个随机字符串(我只是Math.random()用于演示目的)附加到ids 并且当我隐藏 Header 时我不再遇到 Python 图标在主体上消失的问题。这是更新的PythonIcon组件:

import React from "react";

const PythonIcon = (props) => {
  const rand1 = Math.random()
  const rand2 = Math.random()
  return (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 64 64"
      width="64"
      height="64"
      {...props}
    >
      <linearGradient
        id={`pythonLinearGradient1-${rand1}`}
        x1="611.11"
        x2="720.13"
        y1="-280.51"
        y2="-374.3"
        gradientTransform="matrix(.32049 0 0 -.32362 -197.36 -88.951)"
        gradientUnits="userSpaceOnUse"
      >
        <stop stopColor="#5A9FD4" offset="0" />
        <stop stopColor="#306998" offset="1" />
      </linearGradient>
      <path
        fill={`url(#pythonLinearGradient1-${rand1})`}
        strokeWidth=".56976"
        d="m31.344 0c-2.6209 0-5.1278 0.2279-7.2929 0.62674-6.4383 1.1395-7.6348 3.5325-7.6348 7.9197v5.8116h15.27v1.9372h-21.024c-4.4441 0-8.3185 2.6779-9.572 7.7488-1.4244 5.8116-1.4814 9.458 0 15.498 1.0825 4.5011 3.7034 7.7488 8.1476 7.7488h5.2418v-6.9511c0-5.0139 4.3872-9.515 9.572-9.515h15.27c4.2732 0 7.6348-3.4755 7.6348-7.7488v-14.529c0-4.1593-3.4755-7.236-7.6348-7.9197-2.6209-0.45581-5.3558-0.62674-7.9767-0.62674zm-8.2615 4.672c1.5953 0 2.8488 1.3104 2.8488 2.9058 0 1.5953-1.3104 2.9058-2.8488 2.9058-1.5953 0-2.8488-1.3104-2.8488-2.9058 0-1.5953 1.2535-2.9058 2.8488-2.9058z"
      />
      <linearGradient
        id={`pythonLinearGradient2-${rand2}`}
        x1="762.27"
        x2="723.34"
        y1="-431.07"
        y2="-375.99"
        gradientTransform="matrix(.32049 0 0 -.32362 -197.36 -88.951)"
        gradientUnits="userSpaceOnUse"
      >
        <stop stopColor="#FFD43B" offset="0" />
        <stop stopColor="#FFE873" offset="1" />
      </linearGradient>
      <path
        fill={`url(#pythonLinearGradient2-${rand2})`}
        strokeWidth=".56976"
        d="m48.836 16.352v6.7802c0 5.2418-4.4441 9.6859-9.572 9.6859h-15.213c-4.1593 0-7.6348 3.5895-7.6348 7.7488v14.529c0 4.1593 3.5895 6.5523 7.6348 7.7488 4.843 1.4244 9.458 1.6523 15.27 0 3.8744-1.1395 7.6348-3.3616 7.6348-7.7488v-5.8116h-15.27v-1.9372h22.904c4.4441 0 6.0964-3.0767 7.6348-7.7488 1.5953-4.786 1.5384-9.4011 0-15.498-1.0825-4.4441-3.1907-7.7488-7.6348-7.7488zm-8.5464 36.807c1.5953 0 2.8488 1.3104 2.8488 2.9058 0 1.5953-1.3104 2.9058-2.8488 2.9058-1.5953 0-2.8488-1.3105-2.8488-2.9058-0.05698-1.5953 1.2535-2.9058 2.8488-2.9058z"
      />
    </svg>
  );
};

export default PythonIcon;

这是屏幕截图,显示了使用隐藏标题时未隐藏 Python 图标的预期行为display: none

d


推荐阅读