web-dev-qa-db-ja.com

React divへの背景画像としてのSVGコンポーネント

スタイル付きコンポーネントに、反応コンポーネントであるSVGを取得して背景画像として設定しようとしていますが、次のエラーが発生します。

TypeError:シンボル値を文字列に変換できません

SVGコンポーネントコード:

import React from "react";

const testSVG = props => {
  return (
    <svg version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 193.3 129.7">
      <g>
        <g>
          <g>
            <path
              fill="#434343"
              class="st0"
              d="M162.4,116c-4.6,7.5-15.6,13.6-24.4,13.6H16c-8.8,0-12.3-6.2-7.7-13.7c0,0,4.6-7.7,11.1-18.4
                c4.4-7.4,8.9-14.7,13.3-22.1c1.1-1.8,6.1-7.7,6.1-10.1c0-7.3-15-24.9-18.5-30.7C13.5,23.6,8.3,14.9,8.3,14.9
                C3.7,7.4,7.2,1.2,16,1.2c0,0,65.9,0,106.8,0c10,0,25.9-4.5,33.5,3.8c8.7,9.3,15.5,25.4,22.5,36.8c2.6,4.2,14.5,18.3,14.5,23.8
                c-0.1,7.6-16,26.1-19.6,32C167.1,108.3,162.4,116,162.4,116z"
            />
          </g>
        </g>
      </g>
    </svg>
  );
};

export default testSVG;

コンテナコンポーネントコード:

import React, { Component } from "react";
import StepSVG from "../../components/UI/SVGs/Test";

class StepBar extends Component {
  render() {
    const { steps } = this.props;

    return (
      <div>
        {steps
          ? steps.map(step => {
              return (
                <Wrap key={step._id} bg={StepSVG}>
                  <P>
                    {" "}
                    <Link to={"/step/" + step._id}>{step.title} </Link>
                  </P>
                </Wrap>
              );
            })
          : null}
      </div>
    );
  }
}

export default StepBar;

const Wrap = styled.div`
  padding: 30px 30px 0 0;
  display: inline-block;
  background-image: url(${props => props.bg});
`;

私は箱から出してすぐにcreate-react-appを使用しています。

また、スタイル付きコンポーネントを使用せずに試し、インラインスタイルを使用して成功しませんでした。

SVGをコンポーネントとして、このコンテキストでSVGを背景画像として使用することは可能ですか?

7
user8467470

残念ながら、あなたが達成しようとしていることは不可能です。 SVGを実際の.svgファイル(およびそのリンク)として保持するか、CSSの工夫を凝らしてSVGコンポーネントをフォアグラウンドコンポーネントの背後に配置する必要があります。

言い換えると:

<!-- step.svg -->
<svg version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 193.3 129.7">
  <!-- copy paste your svg here -->
</svg>

そしてあなたのコンポーネントで:

import stepSvgUrl from "../../components/UI/SVGs/step.
// ...
<Wrap key={step._id} bg={stepSvgUrl}>

そのようなSVGファイルをインポートすると、create-react-appは生成されたURLを含むWebpackローダーをインポートするSVGに適用します。これはbackground-image cssプロパティ。

お役に立てれば!

3
Kris Selbekk

実際には、SVGがコンポーネントにならないようにして、希望どおりの結果を得る方法があります。

次に、更新されたStepBarコンポーネントを示します。

import React, { Component } from "react";
import StepSVG from "../../components/UI/SVGs/test.svg";
import encodeSVG from '../../lib/encodeSVG';

class StepBar extends Component {
  render() {
    const { steps } = this.props;

    return (
      <div>
        {steps
          ? steps.map(step => {
              return (
                <Wrap key={step._id} bg={StepSVG}>
                  <P>
                    {" "}
                    <Link to={"/step/" + step._id}>{step.title} </Link>
                  </P>
                </Wrap>
              );
            })
          : null}
      </div>
    );
  }
}

export default StepBar;

const Wrap = styled.div`
  padding: 30px 30px 0 0;
  display: inline-block;
  background-image: ${encodeSVG(bg, '#FF9900')};
`;

これがencodeSVG libファイルです:

var symbols = /[\r\n"%#()<>?\[\\\]^`{|}]/g;

function addNameSpace(data) {
  if (data.indexOf('http://www.w3.org/2000/svg') < 0) {
    data = data.replace(/<svg/g, "<svg xmlns='http://www.w3.org/2000/svg'");
  }

  return data;
}

function encodeSVG(data) {
  // Use single quotes instead of double to avoid encoding.
  if (data.indexOf('"') >= 0) {
    data = data.replace(/"/g, "'");
  }

  data = data.replace(/>\s{1,}</g, '><');
  data = data.replace(/\s{2,}/g, ' ');

  return data.replace(symbols, encodeURIComponent);
}

var encode = function(svg, fill) {
  if (fill) {
    svg = svg.replace(/<svg/g, `<svg fill="${fill}"`);
  }
  var namespaced = addNameSpace(svg);
  var dimensionsRemoved = namespaced
    .replace(/height="\w*" /g, '')
    .replace(/width="\w*" /g, '')
    .replace(/height='\w*' /g, '')
    .replace(/width='\w*' /g, '');
  var encoded = encodeSVG(dimensionsRemoved);

  var header = 'data:image/svg+xml,';
  var dataUrl = header + encoded;  

  return `url("${dataUrl}")`;
};

Svgをインポートし、優先ビルドシステム(WebPackなど)でsvgの文字列ローダーを使用し、そのsvgをencodeSVGに渡します。 :)

2
phun-ky
url(`data:image/svg+xml;utf8,${svgTxt}`)

;または

url(`data:image/svg+xml;base64,${btoa(svgTxt)}`)

それでおしまい。

1
user11011301

最終的に、user11011301のソリューションを raw-loader と組み合わせて使用​​してSVGコンテンツをロードしました。私が確信している最もクリーンなソリューションではありませんが、他のWebpackローダーで動作させることができませんでした。

import searchIcon from '../../images/search.svg';

<input style={{backgroundImage: `url(data:image/svg+xml;base64,${btoa(searchIcon)})`}}/>
1
paul.ago

あなたはおそらくそれを文字列に変換するべきです(エラーが指摘するように)。明らかに、Reactコンポーネントを背景画像として使用することはできません。reactコンポーネントは実際にはJavaScriptオブジェクトです(JSXはJSに変換され、次にHTMLに変換されます)。 ReactDOMServer( https://reactjs.org/docs/react-dom-server.html )。

あなたは何かで試すことができます:

ReactDOMServer.renderToString(StepSVG)

または

ReactDOMServer.renderToStaticMarkup(StepSVG)

これが実際に機能するかどうかはテストしていませんが、試してみる価値はあると思います:)

0
Arber Sylejmani