Создание компонентов SVG с областью CSS

Я создаю компоненты React, которые будут отображать различные SVGs:

const Close = ({
  fill, width, height, float,
}) => (
  <svg width={ `${width}px` } height={ `${height}px` } viewBox="0 0 14.48 14.48" style={ { float: `${float}`, cursor: 'pointer' } }>
    <title>x</title>
    <g id="Layer_2" data-name="Layer 2">
      <g id="Background">
        <line style={ { fill: 'none', stroke: `${fill}`, strokeMiterlimit: 10 } } x1="14.13" y1="0.35" x2="0.35" y2="14.13" />
        <line style={ { fill: 'none', stroke: `${fill}`, strokeMiterlimit: 10 } } x1="14.13" y1="14.13" x2="0.35" y2="0.35" />
      </g>
    </g>
  </svg>
);

очень удобно мочь поставить различное приписанное к этому компоненту для того чтобы контролировать размеры, цвет, ЕТК...

однако у меня нет хорошего решения для обработки стилей сухим способом. Примечание line элементы имеют одинаковое значение для style. В настоящее время они написаны inline, потому что если бы я добавил встроенную таблицу стилей, я бы получил имя класса столкновения с другими SVGs я визуализирую в другом месте на странице (наше программное обеспечение SVG использует одни и те же классы снова и снова).

<style scoped> был удален из спецификации:https://github.com/whatwg/html/issues/552

Shadow DOM еще не поддерживается Edge:https://caniuse.com/#feat=shadowdomv1

есть ли другая альтернатива для определения стилей?

3 ответов


Если вы просто хотите высушить код, вы можете создать один объект стиля и повторно использовать его:

const Close = ({
                 fill, width, height, float,
               }) => {
  const style = { fill: 'none', stroke: `${fill}`, strokeMiterlimit: 10 }
  return (
    <svg width={ `${width}px` } height={ `${height}px` } viewBox="0 0 14.48 14.48" style={ { float: `${float}`, cursor: 'pointer' } }>
      <title>x</title>
      <g id="Layer_2" data-name="Layer 2">
        <g id="Background">
          <line style={ style } x1="14.13" y1="0.35" x2="0.35" y2="14.13" />
          <line style={ style } x1="14.13" y1="14.13" x2="0.35" y2="0.35" />
        </g>
      </g>
    </svg>
  );
}

Это также приведет к небольшому повышению производительности, так как в каждом цикле рендеринга будет создано меньше объектов.


чтобы объединить лучшее из обоих миров, вы можете создать файл внешних стилей, как для CSS, но с экспортированными объектами стиля. Затем вы можете импортировать его в любой файл, который в ней нуждается.

например, основной файл:

import React, { Component } from 'react';
import { render } from 'react-dom';
import * as Styles from './svgstyles';

class App extends Component {
  render() {
    return (
      <div>
        <svg width="100" height="200" viewBox="0 0 100 200">  
          <rect x="0" y="0" width="10" height="10" style={Styles.style1} />
          <rect x="15" y="0" width="10" height="10" style={Styles.style2} />
          <rect x="30" y="0" width="10" height="10" style={Styles.style3} />
          <rect x="45" y="0" width="10" height="10" style={Styles.style4} />
          <rect x="0" y="15" width="10" height="10" style={Styles.style4} />
          <rect x="15" y="15" width="10" height="10" style={Styles.style3} />
          <rect x="30" y="15" width="10" height="10" style={Styles.style2} />
          <rect x="45" y="15" width="10" height="10" style={Styles.style1} />
        </svg>
      </div>
    );
  }
}

render(<App />, document.getElementById('root'));

и файл внешних стилей:

export const style1 = {
  stroke: 'red',
  strokeWidth: "1",
  fill: "blue",
}

export const style2 = {
  stroke: 'red',
  strokeWidth: "1",
  fill: "green",
}

export const style3 = {
  stroke: 'red',
  strokeWidth: "1",
  fill: "yellow",
}

export const style4 = {
  ...style3,
  fill: "pink",
}

живой пример здесь


На самом деле, если бы я был на вашем месте, конечно, я использую шрифты вместо SVGs, но для вашего точного вопроса я предпочитаю использовать постоянные переменные внутри моей функции стрелки, как показано ниже:

import React from 'react';

const Close = ({ fill, width, height, float }) => {
  const constStyle = { fill: 'none', stroke: `${fill}`, strokeMiterlimit: 10 };

  return (
    <svg
      width={`${width}px`}
      height={`${height}px`}
      viewBox="0 0 14.48 14.48"
      style={{ float: `${float}`, cursor: 'pointer' }}
    >
      <title>x</title>
      <g id="Layer_2" data-name="Layer 2">
        <g id="Background">
          <line style={constStyle} x1="14.13" y1="0.35" x2="0.35" y2="14.13" />
          <line style={constStyle} x1="14.13" y1="14.13" x2="0.35" y2="0.35" />
        </g>
      </g>
    </svg>
  );
};

export default Close;

даже, я делаю переменные размера линии как props, но я не знаю, в чем конкретно заключается ваш случай.

надеюсь, этот ответ поможет вам.