导入 img 而不是 SVG

Posted

技术标签:

【中文标题】导入 img 而不是 SVG【英文标题】:Importing img instead of SVG 【发布时间】:2022-01-05 00:38:00 【问题描述】:

我最近学习了一个关于构建菜单的教程,我想将它用于我正在整合的网站。该功能似乎正在运行,但我遇到的问题是“我的个人资料”部分的“leftIcon”。我相信 'leftIcon' 仅用于获取 *.svg 文件,我想知道如何将导入的 avatar .jpg 视为左侧图标。

我已附上以下文件的副本,非常感谢有关此事的任何意见。

App.js

import "./index.css";
import  ReactComponent as BellIcon  from "./icons/bell.svg";
import  ReactComponent as MessengerIcon  from "./icons/messenger.svg";
import  ReactComponent as PlusIcon  from "./icons/plus.svg";
import  ReactComponent as CogIcon  from "./icons/cog.svg";
import  ReactComponent as ChevronIcon  from "./icons/chevron.svg";
import  ReactComponent as ArrowIcon  from "./icons/arrow.svg";
import  ReactComponent as BoltIcon  from "./icons/bolt.svg";
import  ReactComponent as MenuIcon  from "./icons/menu.svg";
import avatar from "./assets/userAvatar.jpg";

import React,  useState, useEffect, useRef  from "react";
import  CSSTransition  from "react-transition-group";

function App() 
  return (
    <Navbar>
      <NavItem icon=<PlusIcon /> />
      <NavItem icon=<BellIcon /> />
      <NavItem icon=<MessengerIcon /> />

      <NavItem icon=<MenuIcon />>
        <DropdownMenu></DropdownMenu>
      </NavItem>
    </Navbar>
  );


function Navbar(props) 
  return (
    <nav className="navbar">
      <ul className="navbar-nav">props.children</ul>
    </nav>
  );


function NavItem(props) 
  const [open, setOpen] = useState(false);

  return (
    <li className="nav-item">
      <a href="#" className="icon-button" onClick=() => setOpen(!open)>
        props.icon
      </a>

      open && props.children
    </li>
  );


function DropdownMenu() 
  const [activeMenu, setActiveMenu] = useState("main");
  const [menuHeight, setMenuHeight] = useState(null);
  const dropdownRef = useRef(null);

  useEffect(() => 
    setMenuHeight(dropdownRef.current?.firstChild.offsetHeight);
  , []);

  function calcHeight(el) 
    const height = el.offsetHeight;
    setMenuHeight(height);
  

  function DropdownItem(props) 
    return (
      <a
        href="#"
        className="menu-item"
        onClick=() => props.goToMenu && setActiveMenu(props.goToMenu)
      >
        <span className="icon-button">props.leftIcon</span>
        props.children
        <span className="icon-right">props.rightIcon</span>
      </a>
    );
  

  return (
    <div className="dropdown" style= height: menuHeight  ref=dropdownRef>
      <CSSTransition
        in=activeMenu === "main"
        timeout=500
        classNames="menu-primary"
        unmountOnExit
        onEnter=calcHeight
      >
        <div className="menu">
          <DropdownItem leftIcon=avatar>My Profile</DropdownItem>
          <DropdownItem
            leftIcon=<CogIcon />
            rightIcon=<ChevronIcon />
            goToMenu="settings"
          >
            Settings
          </DropdownItem>
          <DropdownItem
            leftIcon="????"
            rightIcon=<ChevronIcon />
            goToMenu="animals"
          >
            Animals
          </DropdownItem>
        </div>
      </CSSTransition>

      <CSSTransition
        in=activeMenu === "settings"
        timeout=500
        classNames="menu-secondary"
        unmountOnExit
        onEnter=calcHeight
      >
        <div className="menu">
          <DropdownItem goToMenu="main" leftIcon=<ArrowIcon />>
            <h2>My Tutorial</h2>
          </DropdownItem>
          <DropdownItem leftIcon=<BoltIcon />>html</DropdownItem>
          <DropdownItem leftIcon=<BoltIcon />>CSS</DropdownItem>
          <DropdownItem leftIcon=<BoltIcon />>javascript</DropdownItem>
          <DropdownItem leftIcon=<BoltIcon />>Awesome!</DropdownItem>
        </div>
      </CSSTransition>

      <CSSTransition
        in=activeMenu === "animals"
        timeout=500
        classNames="menu-secondary"
        unmountOnExit
        onEnter=calcHeight
      >
        <div className="menu">
          <DropdownItem goToMenu="main" leftIcon=<ArrowIcon />>
            <h2>Animals</h2>
          </DropdownItem>
          <DropdownItem leftIcon="????">Kangaroo</DropdownItem>
          <DropdownItem leftIcon="????">Frog</DropdownItem>
          <DropdownItem leftIcon="????">Horse?</DropdownItem>
          <DropdownItem leftIcon="????">Hedgehog</DropdownItem>
        </div>
      </CSSTransition>
    </div>
  );


export default App;

index.css

body 
  margin: 0;
  background: #151616;
  font-family: roboto;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;


code 
  font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
    monospace;


:root 
  --bg: #242526;
  --bg-accent: #484a4d;
  --text-color: #dadce1;
  --nav-size: 60px;
  --border: 1px solid #474a4d;
  --border-radius: 8px;
  --speed: 500ms;


ul 
  list-style: none;
  margin: 0;
  padding: 0;


a 
  color: var(--text-color);
  text-decoration: none;


/* Top Navigation Bar */

/* <nav> */
.navbar 
  height: var(--nav-size);
  background-color: var(--bg);
  padding: 0 1rem;
  border-bottom: var(--border);


/* <ul> */
.navbar-nav 
  max-width: 100%;
  height: 100%;
  display: flex;
  justify-content: flex-start;


/* <li> */
.nav-item 
  width: calc(var(--nav-size) * 0.8);
  display: flex;
  align-items: center;
  justify-content: center;


/* Icon Button */
.icon-button 
  --button-size: calc(var(--nav-size) * 0.5);
  width: var(--button-size);
  height: var(--button-size);
  background-color: #484a4d;
  border-radius: 50%;
  padding: 5px;
  margin: 2px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: filter 300ms;


.icon-button:hover 
  filter: brightness(1.2);


.icon-button svg 
  fill: var(--text-color);
  width: 20px;
  height: 20px;


/* Dropdown Menu */

.dropdown 
  position: absolute;
  top: 58px;
  width: 300px;
  transform: translateX(45%);
  background-color: var(--bg);
  border: var(--border);
  border-radius: var(--border-radius);
  padding: 1rem;
  overflow: hidden;
  transition: height var(--speed) ease;


.menu 
  width: 100%;


.menu-item 
  height: 50px;
  display: flex;
  align-items: center;
  border-radius: var(--border-radius);
  transition: background var(--speed);
  padding: 0.5rem;


.menu-item .icon-button 
  margin-right: 0.5rem;


.menu-item .icon-button:hover 
  filter: none;


.menu-item:hover 
  background-color: #525357;


.icon-right 
  margin-left: auto;


/* CSSTransition classes  */
.menu-primary-enter 
  position: absolute;
  transform: translateX(-110%);

.menu-primary-enter-active 
  transform: translateX(0%);
  transition: all var(--speed) ease;

.menu-primary-exit 
  position: absolute;

.menu-primary-exit-active 
  transform: translateX(-110%);
  transition: all var(--speed) ease;


.menu-secondary-enter 
  transform: translateX(110%);

.menu-secondary-enter-active 
  transform: translateX(0%);
  transition: all var(--speed) ease;

.menu-secondary-exit 

.menu-secondary-exit-active 
  transform: translateX(110%);
  transition: all var(--speed) ease;


【问题讨论】:

【参考方案1】:

将其作为组件而不是字符串传递:

import avatar from "./icons/avatar.jpg";
const avatarComp = (<img src=avatar    />);



<DropdownItem leftIcon=avatarComp>My Profile</DropdownItem>

const Func =(function () 
  return (<img src=avatar    />);
);
const avatarComp = (<Func/>);

<DropdownItem leftIcon=avatarComp>My Profile</DropdownItem>

这里是沙盒链接:https://codesandbox.io/s/suspicious-glade-zjtq6

【讨论】:

这非常有效。感谢您对此的建议。 除了配置文件 img 之外,我如何删除灰色背景?我似乎无法只删除一个的填充 使用更高的百分比或使用 CSS 转换比例放大图像:var avatarComp = &lt;img src=avatar alt="avatar" height="150%" width="150%" style=transform:'scale(1.5)' /&gt;

以上是关于导入 img 而不是 SVG的主要内容,如果未能解决你的问题,请参考以下文章

从另一个文档导入 SVG 元素,而不会丢失原始文件中的 CSS <style>

如何将 svg 文件导入 Vue 组件?

Flexbox 使用原始 SVG 宽度而不是缩放宽度

添加自定义加载微调器(SVG)reactjs

在画布html5上导入图像

SVG 导入器不导入相同大小的 SVG