Vue.jsでSVGが正しく表示されなかった時の対応 (2)

354
NO IMAGE

前回、Vue.jsでSVGファイルを表示した際に、全然違う見た目で表示される問題と、その解決方法について説明しました。
(左:元のSVG、右:表示されたSVG)。

原因は、Vue.jsではstyleタグが認識されないということでした。
その解決方法として、

  1. styleタグをsvg:styleタグに書き換える(vueファイルにベタにSVGを書く場合はこれで良い)
  2. SVGファイル内のstyle定義をvueファイルに定義する
  3. デザイナーにお願いして、styleは要素でなく属性にしてもらう

を紹介しました。

1の方法で対応していたときに、もう一つの問題が発生したので、紹介します。

もう一つの問題

下図のような2つのSVGファイルを、styleタグをsvg:styleタグに書き換えて、ページ内に配置したのですが、右側のSVGのスタイルがおかしなものになってしまいました。両方のスタイルが重ね合わされた感じになってます。

  • 表示したいSVG
  • 表示されたSVG

SVGのソースコードを見てみたところ、どちらのファイルもclassが"a"になっていました。

左側のSVG

<svg xmlns="http://www.w3.org/2000/svg" width="17.95" height="17.95" viewBox="0 0 17.95 17.95">
  <defs>
    <svg:style>.a{fill:none;stroke:#7c7c7c;stroke-linecap:round;stroke-linejoin:round;stroke-width:2px;}</svg:style>
  </defs>
  <g transform="translate(1 1)">
    <path class="a" d="M6.272,4.5H18.678A1.772,1.772,0,0,1,20.45,6.272V18.678a1.772,1.772,0,0,1-1.772,1.772H6.272A1.772,1.772,0,0,1,4.5,18.678V6.272A1.772,1.772,0,0,1,6.272,4.5Z" transform="translate(-4.5 -4.5)" />
    <path class="a" d="M18,12v7.089" transform="translate(-10.025 -7.569)" />
    <path class="a" d="M12,18h7.089" transform="translate(-7.569 -10.025)" />
  </g>
</svg>

右側のSVG

<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
  <defs>
    <svg:style>.a{fill:#eb7070;}</style>
  </defs>
  <path class="a" d="M15,3A12,12,0,1,0,27,15,12,12,0,0,0,15,3Zm6,13.2H9V13.8H21Z" transform="translate(-3 -3)" />
</svg>

classのスコープはSVGファイル内かと思っていたら、どうやらそうではなさそうです。

style定義がSVGファイル内で閉じるように、svgにidを付与しました。

左側のSVG

<svg xmlns="http://www.w3.org/2000/svg" id="plus-square" width="17.95" height="17.95" viewBox="0 0 17.95 17.95">
  <defs>
    <svg:style>#plus-square .a{fill:none;stroke:#7c7c7c;stroke-linecap:round;stroke-linejoin:round;stroke-width:2px;}</svg:style>
  </defs>
  <g transform="translate(1 1)">
    <path class="a" d="M6.272,4.5H18.678A1.772,1.772,0,0,1,20.45,6.272V18.678a1.772,1.772,0,0,1-1.772,1.772H6.272A1.772,1.772,0,0,1,4.5,18.678V6.272A1.772,1.772,0,0,1,6.272,4.5Z" transform="translate(-4.5 -4.5)" />
    <path class="a" d="M18,12v7.089" transform="translate(-10.025 -7.569)" />
    <path class="a" d="M12,18h7.089" transform="translate(-7.569 -10.025)" />
  </g>
</svg>

右側のSVG

<svg xmlns="http://www.w3.org/2000/svg" id="remove-circle" width="24" height="24" viewBox="0 0 24 24">
  <defs>
    <svg:style>#remove-circle .a{fill:#eb7070;}</style>
  </defs>
  <path class="a" d="M15,3A12,12,0,1,0,27,15,12,12,0,0,0,15,3Zm6,13.2H9V13.8H21Z" transform="translate(-3 -3)" />
</svg>

上記のように書き換えたら、思った通りの表示になりました。

結論

styleタグを含むSVGファイルを正しく表示させるには、以下の方法があります。

  1. styleタグをsvg:styleタグに書き換える(vueファイルにベタにSVGを書く場合はこれで良い)
  2. SVGファイル内のstyle定義をvueファイルに定義する
  3. デザイナーにお願いして、styleは要素でなく属性にしてもらう

ただし、1、3の場合は、style定義がグローバルで一意になるように注意する。