【问题标题】:In React, Javascript, how to convert object with SVG element parameters into actual SVG elements在 React、Javascript 中,如何将带有 SVG 元素参数的对象转换为实际的 SVG 元素
【发布时间】:2023-02-03 18:37:28
【问题描述】:
const courtStructure = [
    { class: 'legend-rect', shape: 'rect', x: 0, y: TLP + 38, width: 50, height: 8, fill: headerStyle.backgroundColor }, // rectangle behind legend
    { class: 'backboard', shape: 'line', x1: 22, x2: 28, y1: 3.75, y2: 3.75, stroke: hoopColor, opacity: hoopOpacity, strokeWidth: 0.5 }, // backboard
    { class: 'rim', shape: 'circle', r: 0.95, cx: 25, cy: 5.1, opacity: hoopOpacity, fill: hoopColor }, // the circle part of rim
    { class: 'back-iron', shape: 'rect', x: 24.625, y: 3.95, width: 0.75, height: 0.5, stroke: 0, opacity: hoopOpacity, fill: hoopColor } // back iron on rim
];

<rect
    className='legend-rect'
    x={0}
    y={TLP + 38}
    width={50}
    height={8}
    fill={headerStyle.backgroundColor}
/>
...

我们有 courtStructure 对象数组,我们想 .map() 数组并创建描述的 SVG 元素。第一个rect 的示例如上所示。 courtStructure 中每个对象中的键应创建为 SVG 元素上的字段。 shape 确定元素类型。

实现这一目标最困难的部分似乎是:

  • 创建正确的元素(矩形、线、圆等)
  • 处理不同对象对 SVG 具有不同键/参数的事实

这可能吗?

【问题讨论】:

    标签: javascript svg ecmascript-6


    【解决方案1】:

    您可以尝试declaringCustomTag,如下所示:

    import * as React from 'react';
    import './style.css';
    import { courtStructure } from './data';
    
    export default function App() {
      const headerStyle = { backgroundColor: 'blue' };
      const TLP = 0;
      const hoopColor = 'green';
      const hoopOpacity = 1;
    
      const data = courtStructure(TLP, headerStyle, hoopColor, hoopOpacity);
      const CustomTag = ({ name, children, ...props }) => {
        return React.createElement(name, props, children);
      };
      return (
        <svg viewBox="0 0 220 100" xmlns="http://www.w3.org/2000/svg">
          {data.map((a) => (
            <CustomTag
              name={a.shape}
              children=""
              className={a.class}
              x={a.x}
              y={a.y}
              width={a.width}
              height={a.height}
              cx={a.cx}
              cy={a.cy}
              r={a.r}
              stroke={a.stroke}
              stroke-width={a.strokeWidth}
              fill={a.fill}
              x1={a.x1}
              y1={a.y1}
              x2={a.x2}
              y2={a.y2}
              opacity={a.opacity}
            ></CustomTag>
          ))}
        </svg>
      );
    }
    

    【讨论】:

      【解决方案2】:

      对于每个对象,提取需要“名称映射”的属性,例如shapeclass等。其余属性保存在单个对象中,并作为spread attributes传递给 React。

      然后,您可以通过dynamic tags 或直接通过React.createElement 创建组件:

      const components = courtStructure.map(
        ({shape: Shape, class: className, ...props}) => {
          return <Shape className={className} {...props} />
          // or
          return React.createElement(Shape, {className, ...props})
        }
      )
      

      另见

      【讨论】:

        【解决方案3】:

        我可能会更改对象结构的设置方式以将形状与实际属性分开,并使属性的键与您传递给元素的属性相匹配,如下所示:

        const courtStructure = [
            { 
                shape: 'rect', 
                attributes: {
                    className: 'legend-rect', 
                    x: 0, 
                    y: TLP + 38, 
                    width: 50, 
                    height: 8, 
                    fill: headerStyle.backgroundColor 
                }
            }, // rectangle behind legend
            ...
        ];
        

        通过这种方式,您可以映射数组并为形状创建一个 switch 语句来决定要渲染的元素,并解构 svg 元素上的属性。是这样的:

        {courtStructure.map((element) => {
            switch(element.shape) {
                case 'rect':
                    return (
                        <rect {...element.attributes} />
                    );
                case 'line':
                    return (
                        <line {...element.attributes} />
                    );
                case 'circle':
                    return (
                        <circle {...element.attributes} />
                    );
            }
        })}
        

        您显然也可以将此逻辑重构为它自己的 Shape 组件以使其更清晰!

        【讨论】:

          猜你喜欢
          • 2020-10-13
          • 2019-02-02
          • 2014-05-13
          • 2014-07-15
          • 1970-01-01
          • 2016-09-12
          • 2013-02-02
          • 2019-08-05
          • 1970-01-01
          相关资源
          最近更新 更多