最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Iterating & Rendering SVG in loop - Stack Overflow

programmeradmin2浏览0评论

I've been doing iteration map with react for quite long now with many success. The only thing I haven't encounter is rendering SVG with iteration.

Start with react ponent setting up iteration mp and importing array of data from ./data.js.

Cards.js

import React from 'react';
import data from './data';

const icons = data.map(icon => (
  <>
   <div><span>{icon.svg}</span> {icon.type}</div>
  </>
));

const Cards = () => (<>{ icons }</>);

export default Cards;

Array of data...

data.js

export default[
 {
   svg: './icons/menu.svg',
   type: Menu
 },
{
   svg: './icons/home.svg',
   type: Home
 },
 {
   svg: './icons/clock.svg',
   type: History
 }
]

Problem is, its unable to render .svg following directory but end up rending string ./icons/xxx.svg instead.

I've tried another method..

svg: require('./icons/clock.svg'),

... still getting same result. I'm Running out of idea. Any suggestions? I understand require('') worked with JSX img tag... But I wanetd .svg files only, is there a way to import svg files into data array?

I've been doing iteration map with react for quite long now with many success. The only thing I haven't encounter is rendering SVG with iteration.

Start with react ponent setting up iteration mp and importing array of data from ./data.js.

Cards.js

import React from 'react';
import data from './data';

const icons = data.map(icon => (
  <>
   <div><span>{icon.svg}</span> {icon.type}</div>
  </>
));

const Cards = () => (<>{ icons }</>);

export default Cards;

Array of data...

data.js

export default[
 {
   svg: './icons/menu.svg',
   type: Menu
 },
{
   svg: './icons/home.svg',
   type: Home
 },
 {
   svg: './icons/clock.svg',
   type: History
 }
]

Problem is, its unable to render .svg following directory but end up rending string ./icons/xxx.svg instead.

I've tried another method..

svg: require('./icons/clock.svg'),

... still getting same result. I'm Running out of idea. Any suggestions? I understand require('') worked with JSX img tag... But I wanetd .svg files only, is there a way to import svg files into data array?

Share Improve this question edited Oct 12, 2018 at 17:38 sirrus asked Oct 12, 2018 at 17:32 sirrussirrus 3431 gold badge7 silver badges17 bronze badges 1
  • 1 Have you tried this <div><span>{require(icon.svg)}</span> {icon.type}</div> – Hemadri Dasari Commented Oct 12, 2018 at 17:52
Add a ment  | 

4 Answers 4

Reset to default 4

Try setting it up like so:

import menu from './icons/menu.svg';
import home from './icons/home.svg';
import clock from './icons/clock.svg';

export default[
 {
   svg: menu,
   type: 'Menu'
 },
{
   svg: home,
   type: 'Home'
 },
 {
   svg: clock,
   type: 'History'
 }
]

And implement it like this:

<div>
  <span>
    <img src={icon.svg} />
  </span> 
  {icon.type}
</div>

Thank you guys taking time to help... Those method do work, gave me idea and I am keeping note of it. But it was not exactly what I was looking for since it'd have to use <img> tags which will not allow me to adjust size, color or etc. I want to avoid going back and forth between code editor and illustration programs. Fortunately, I found alternative solution, it may be tedious but it works. Here what I did...

Start with creating React PropTypes ponent..

Icon.js

import React from 'react';
import PropTypes from 'prop-types';

const config = {
  svg: {
    display: 'flex-inline',
    margin: '0 auto'
  }
};

const Icons = props => (
  <svg
    style={config.svg}
    width={`${props.size}`}
    height={`${props.size}`}
    viewBox={`0 0 512 512`}
    className={props.className}
  >
    <path d={props.icon} />
  </svg>
);

Icons.propTypes = {
  icon: PropTypes.string.isRequired,
  size: PropTypes.number.isRequired,
  color: PropTypes.string,
  className: PropTypes.string.isRequired
};

Icons.defaultProps = {
  size: 32
};

Create another file and include array of SVG path with defined name eg. menu, home, clock

icons.js

export const SVGicon = {
  menu: /*Insert your SVG path here starting with 'M...*/, 

  home: /*Insert your SVG  path here starting with 'M...*/,

  clock: /*Insert your SVG path here starting with 'M...*/,

}

Back to data.js and modify a little (Thank you Ted!)

data.js

import { SVGicon } from './icons'

export default[
  {
    svg: SVGicon.menu,
    type: 'Henu'
  },
  {
    svg: SVGicon.home,
    type: 'Home'
  },
  {
    svg: SVGicon.clock,
    type: 'History'
  }
]

Back to react ponents and modify a little...

Cards.js

import React from 'react';
import data from './data';
import Icon from './Icon'; /* PropType Component */

const icons = data.map(icon => (
 <React.Fragment>
  <Icons icon={icon.svg} className="svg-icon" size={12} />
 </React.Fragment>
));

const Cards = () => (<React.Fragment>{ icons }</React.Fragment>);

export default Cards;

and the css following className="svg-icon" to adjust color, effect and etc

main.scss

.svg-icon{
  fill: rgba(blue, .5);
  transition: fill .3s ease-out;
  &:hover{
    fill: rgba(red, 1);
 }

This should show array of different SVG icons, with ability to control color, size and etc... Hope this help

Keep your data as it is and use require to render it

<div>
  <span>
    {require(icon.svg)}
  </span> 
  {icon.type}
</div>

I would have added this as a ment to @sirrius, but not enough reputations :)

I followed the solution provided but my icons were not visible. This is because the view port is still taking static values, instead of the dynamic size values for width and height.

So instead of:

const Icons = props => (
  <svg
    style={config.svg}
    width={`${props.size}`}
    height={`${props.size}`}
    viewBox={`0 0 512 512`}
    className={props.className}
  >
    <path d={props.icon} />
  </svg>
);

which would have the icons taking a viewBox height and width of 512 irrespective of the size prop (imagine having an svg of size 32 inside a 512 viewBox, it could appear to be out of sight cause of the dimensions are not proportional).

You should have:

const Icons = props => (
  <svg
    style={config.svg}
    width={`${props.size}`}
    height={`${props.size}`}
    viewBox={`0 0 ${props.size} ${props.size}`}
    className={props.className}
  >
    <path d={props.icon} />
  </svg>
);

This adjusts the viewBox with respect to the size provided.

发布评论

评论列表(0)

  1. 暂无评论