【问题标题】:How to use an SVG file in a SvgIcon in Material-UI如何在 Material-UI 的 SvgIcon 中使用 SVG 文件
【发布时间】:2016-11-25 09:54:27
【问题描述】:

我有一个 SVG 文件,我想用它制作一个 SvgIcon 组件,我应该怎么做?

documentation 中,所有示例都使用预定义的材质图标或<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" /> 的奇怪符号,我不知道它是什么!

【问题讨论】:

    标签: svg material-ui


    【解决方案1】:

    1。使用<Icon/> 组件和<img/> 元素

    为了使用 SVG 文件作为图标,我使用了 <Icon/> 组件,其中包含 <img/> 元素,将 height: 100% 设置为 img 元素,将 textAlign: center 设置为 root<Icon/> 组件成功了:

    JSX:

    import Icon from '@material-ui/core/Icon';
    import { makeStyles } from '@material-ui/styles';
    ...
    
    <Icon classes={{root: classes.iconRoot}}>
      <img className={classes.imageIcon} src="/graphics/firebase-logo.svg"/>
    </Icon>
    

    样式:

    const useStyles = makeStyles({
      imageIcon: {
        height: '100%'
      },
      iconRoot: {
        textAlign: 'center'
      }
    });
    

    结果:

    更新

    正如 Lorenz Haase 在 cmets 中提到的,底部的 SVG 有轻微的剪切,如果我们使用 flexbox 并继承宽度和高度,它可以修复:

    const useStyles = makeStyles({
      imageIcon: {
        display: 'flex',
        height: 'inherit',
        width: 'inherit'
      }
    });
    

    2。使用&lt;SvgIcon/&gt; 组件和@svgr/webpack webpack 加载器

    根据official MUI documentation,我们可以使用&lt;SvgIcon/&gt; 组件道具,并有一个@svgr/webpack 加载器使用ESM 导入加载.svg 文件。

    组件道具

    即使您的图标保存在 .svg 格式。 svgr 有加载器来导入 SVG 文件并使用它们 作为 React 组件。例如,使用 webpack:

    // webpack.config.js
    {
      test: /\.svg$/,
      use: ['@svgr/webpack'],
    }
    
    // ---
    import StarIcon from './star.svg';
    
    <SvgIcon component={StarIcon} viewBox="0 0 600 476.6" />
    

    它也可以与“url-loader”或“file-loader”一起使用。它是 Create React App 使用的方法。

    // webpack.config.js
    {
      test: /\.svg$/,
      use: ['@svgr/webpack', 'url-loader'],
    }
    
    // ---
    import { ReactComponent as StarIcon } from './star.svg';
    
    <SvgIcon component={StarIcon} viewBox="0 0 600 476.6" />
    

    【讨论】:

    • 我尝试了这个独奏,虽然它有效,但我无法用不同的颜色来设计它,似乎不可能
    • @MaxCarroll 不使用 material-ui 的情况下,您一般如何设置 SVG 文件的样式?我不认为它会发生,它不会那样工作。更多详情请查看img-src-svg-changing-the-styles-with-css
    • 我后来发现了它,因为 svg 在 svg 中硬编码了填充颜色,对 svg 进行了一些编辑就可以了。您可以使用 css 使用属性 stroke 和 fill 设置 svg 样式。
    • 这是一个很好的解决方案,但可以进行优化。正如您在答案提供的图片中看到的那样,firebase 徽标在底部被切断(应该如下所示:firebase.google.com/brand-guidelines)调整样式解决了这个问题:const useStyles = makeStyles({ imageIcon: { display: 'flex', height: 'inherit', width: 'inherit', } }); 图像不会被切断。不再需要根样式,并且图像从父图标组件获取其尺寸。
    • @LorenzHaase 我没有注意到它在底部被切掉了,很好。我会检查规则,我会更新我的答案,谢谢。
    【解决方案2】:

    &lt;path /&gt; 是 SVG 路径,即 SVG 的内部位。 SvgIcon 组件确实应该能够采取路径,但它没有:(

    您可以创建一个类似https://github.com/callemall/material-ui/blob/56c113217d7d05d8bb0712771b727df81984d04b/src/svg-icons/action/home.js的组件

    用您的 svg 源代替 path。 (我建议使用https://jakearchibald.github.io/svgomg/ 将其缩小一点)

    【讨论】:

    • 路径是硬编解码器,不能像我们使用 png 那样通过加载 svg 来完成吗?
    • 我不太明白这个答案 :( 我在这个答案的任何地方都看不到 svg 文件的路径
    • 本期共有两种路径。有 1) 路径,如 svg 文件位于哪里,然后有 2) SVG 特定 路径,它是包含信息的 SVG 元素的属性关于如何绘制自己。
    【解决方案3】:

    您可以直接将 SVG 作为 React 组件导入并在 &lt;SvgIcon&gt; 中使用它们:

    import React from "react";
    import { ReactComponent as Logo } from "./logo.svg";
    import SvgIcon from "@material-ui/core/SvgIcon";
    
    const App = () => (
      <SvgIcon>
        <Logo />
      </SvgIcon>
    );
    
    export default App;
    

    另请参阅:https://create-react-app.dev/docs/adding-images-fonts-and-files/#adding-svgs

    不幸的是,React 似乎还不能渲染所有类型的 SVG(例如,用 Inkscape、Illustrator 修改)。但至少 create-react-app 项目中的默认 logo.svg 有效。

    【讨论】:

    • 非常感谢!你的回答对我有用!猜猜这对你来说很熟悉,但如果有人想将 InkScape 或 Illustrator svgs 与 React 一起使用,你可以使用 github.com/svg/svgo 客户端来实现。
    【解决方案4】:

    要获取SvgIcon的路径,用文本编辑器打开svg文件,复制对应的路径表达式。

    【讨论】:

      【解决方案5】:

      对我有用的解决方案如下

       import React from 'react';
       import pure from 'recompose/pure';
       import {SvgIcon} from '@material-ui/core';
      
       let smile = (props) => (
         <SvgIcon {...props} >
      <path d="M256,32C132.281,32,32,132.281,32,256s100.281,224,224,224s224-100.281,224-224S379.719,32,256,32z M256,448
      c-105.875,0-192-86.125-192-192S150.125,64,256,64s192,86.125,192,192S361.875,448,256,448z M160,192c0-26.5,14.313-48,32-48
      s32,21.5,32,48c0,26.531-14.313,48-32,48S160,218.531,160,192z M288,192c0-26.5,14.313-48,32-48s32,21.5,32,48
      c0,26.531-14.313,48-32,48S288,218.531,288,192z M384,288c-16.594,56.875-68.75,96-128,96c-59.266,0-111.406-39.125-128-96"/>
         </SvgIcon>
       );
      
       smile = pure(smile);
       smile.displayName = 'smile';     
       smile.muiName = 'SvgIcon';
      
       export default smile;
      

      Check this example of material ui icon

      【讨论】:

      • 什么是 ````import pure from recompose/pure ?```
      【解决方案6】:

      SvgIcon 并非用于此目的。更多关于这个@@Github.

      你可能正在寻找这个startIcon={&lt;img src={google}&gt;&lt;/img&gt;}

      import google from "../../Assets/img/google.svg";
      import GitHubIcon from "@material-ui/icons/GitHub";
      const useStyles = makeStyles((theme) => ({
               root: {
                      display: "flex",
                      flexDirection: "column",
                      margin: theme.spacing(1),
                      },
                button: {
                     margin: "0.5rem",
                        },
                googleStyle: {
                      fillColor: theme.palette.primary.main,
                          },
                    }));
      
      export default function ContainedButtons() {
        const classes = useStyles();
         return (
        <div>
        <Button
          variant="contained"
          color="secondary"
          className={classes.button}
          startIcon={<img src={google}></img>}
        >
          Login With Google
        </Button>
        <Button
          variant="contained"
          color="secondary"
          className={classes.button}
          startIcon={<GitHubIcon />}
        >
          Login with GitHub
        </Button>
      </div>
      );
      }
      

      【讨论】:

      • 这可能是正确的答案。绝对应该更高。为我工作。谢谢!
      【解决方案7】:

      如果制作多个图标,您可能不想重复已接受答案中引用的示例中的所有样板。您可以使用包装组件生成器,例如:

      const wrapSvgPath = (path, viewBox='0 0 24 24') => (props) => (
          <SvgIcon {...props} viewBox={viewBox}>{path}</SvgIcon>
      )
      

      类似:

      const facebookPath = (<path
              d="M17,2V2H17V6H15C14.31,6 14,6.81 14,7.5V10H14L17,10V14H14V22H10V14H7V10H10V6A4,4 0 0,1 14,2H17Z" />
      )
      export const FacebookIcon = wrapSvgPath(facebookPath)
      

      【讨论】:

        【解决方案8】:

        在编辑器中打开您的 svg 文件(例如:vscode)。你会看到类似这样的文件结构 ->

        <svg width="27" height="28" viewBox="0 0 27 28" fill="none" xmlns="http://www.w3.org/2000/svg">
        <path d="M5.91942 27.5138L6.15827 26.984L8.69599 21.1562H8.68852L13.5027 10.3812L18.3542 21.1562H18.3467L21.1083 27.5138H26.2509L15.8687 4.72523L13.5698 0L0.933594 27.5138H5.91942Z" fill="#A7A9AC"/>
        </svg>
        

        然后转到您的反应组件,将路径替换为您自己的路径。这应该有效。添加样式以自定义更改设计。

        【讨论】:

          【解决方案9】:
          import SvgIcon from '@material-ui/core/SvgIcon'
          import Register from "./../../media/register.svg"
          import React from 'react';
          
          const getSvgIconMaterial = (Icon: string, props?: any) => {
              return (
                  <SvgIcon component="object">
                      <embed type="image/svg+xml" src={Icon} style={{ height: "100%" }} />
                  </SvgIcon>
              );
          };
          

          这样使用

          <>{getSvgIconMaterial(Register)}</>
          

          可能并不完美,但效果很好。也许添加一个小的填充/边距。

          【讨论】:

            猜你喜欢
            • 2019-09-12
            • 2018-09-25
            • 2020-09-07
            • 2021-10-25
            • 2022-11-27
            • 2019-09-09
            • 1970-01-01
            • 2017-07-06
            • 2016-12-07
            相关资源
            最近更新 更多