2012年6月3日日曜日

svgで2重線(線の中抜き)を実現する

svgを使って線を描画する際,2重線を引きたいケースは結構ある.だが,点線にする方法や端点の形を設定する方法はあっても,線を2重にする方法は定義されていない.従って,今ある仕様の中で実現する方法を探ることとなるのだが,結構使い途のあるやり方が見つかったので公開する.

線を2重化するやり方としては,ストローク色の異なる同じ線を2つ重ねる方法がまず思い浮かぶ.ただこの方法では中抜き担当の線の色が残ってしまう.そこでmask要素を使って線の描画にマスクを掛けることを考えたが,それでも線の本体と繰り抜く線の2つの要素を定義せねばならず,後々の修正が面倒である.

そこで,g要素を使ってベースとなる図形をグループ化し,それをuse要素を使ってmask要素から参照する方法をとってみた.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 200">
    <mask id="mask8" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse" x="0" y="0" width="200" height="200">
        <rect width="200" height="200" fill="white"/>
        <use xlink:href="#lines" x="0" y="0" stroke-width="4" stroke="black"/>
    </mask>
    <g mask="url(#mask8)" stroke-width="8" stroke="red">
        <g id="lines" fill="none" stroke-linecap="round">
            <path d="M 100,150 m -80,-100 q 80,200 160,0"/>
            <rect x="50" y="50" width="100" height="100"/>
            <circle cx="70" cy="70" r="50"/>
        </g>
    </g>
</svg>
  1. 2重線を設定したい図形をg要素でグループ化する.stroke,stroke-width属性は未設定のまま.
  2. mask要素を定義し,1のグループをuse要素を使ってコピーする.ここでstrokeにblackを,stroke-widthに中抜きしたい太さを設定する.また背景色を白とする.
  3. 1のグループを更にg要素で囲み,strokeに任意の色を,stroke-widthに任意の太さを設定する.
この2重のg要素を定義するのがミソで,これで線の定義を使いまわすことが出来るようになった.このテクニックは意外に応用範囲が広いかもしれない.

    2 件のコメント:

    1. はじめまして、
      最近SVGをはじめたものなのですが、サイトとブログを参考させてもらっています。直接記事と関係ない質問なんですが、

      ttp://www.h2.dion.ne.jp/~defghi/svgMemo/svgMemo_05.htm

      この、外部svgを参照してシンボルを読み出す方法がやってみてもどうしてもできません。このページはうまく表示できるので、環境に問題はないと思うんですが、これってたとえば、英字のパスをシンボル化してidをそれぞれにふって、別のsvgファイルのuseでid指定してパスを読み出し、useでstyle指定してやればタグはすっきりするし、よく使うシンボルなんかはこの方法で別に格納するほうがイイ!ってことだと思うんですが、なぜかどうしてもその格納してあるファイルとリンクできないらしく、ためしにこのページとまったく同じ文章でやってみてもうまくいきません。

      ↑ちなみにネット上にアップロードしてないと読み出せないとかってオチありえますか?

      よろしければご返答お願いします

      返信削除
      返信
      1. 当方の環境では正しく動作しています.

        まず,作成した2つのsvgファイルをそれぞれfirefox等のブラウザで表示してみて下さい.symbolを定義したsvgファイルに問題がなければ,何も表示されないはずです.逆にxmlとして問題があるとブラウザがエラーを表示します.

        また,保存したファイルの文字エンコーディング方式を確認してみましょう.windows環境でテキストを編集していると,知らない間にcp932(shift-jis)形式に変換されてしまうことがあります.こうなるとテキストとしては正しい構文でも,xmlファイルとしておかしいものとして扱われてしまうケースがあります.
        xml宣言部のencodingを揃えるか,svgファイルをutf-8で保存しなおしてもう一度試してみて下さい.


        (当サイトでは全てutf-8で構築しています)

        削除