Liner Note

{ Connecting data makes web more familiar }

SVGのパス(線)の一部の色を変える

路線図

今、こんな感じのSVG鉄道路線図を作っています。

図の中で運休中の部分は色を変えたいなと思ったのですが、どうやらこの一本一本を構成する path 要素は一色だけで途中から色を変えるってのはどうも難しいようです。

SVGのパス(path要素)の一部分だけ色を変えたい。例えば、この路線図のA〜Bだけ色を変えるとか https://t.co/FyeF7Z6AOt

— Hashimoto Naoki (@hashcc)

2014, 3月 25

対象の図形はこんな感じ。

コードを抜粋

<g> <path fill="none" stroke="#C30D23" stroke-width="15" stroke-linecap="round" stroke-miterlimit="10" d="M53.9,265.1v-71.7 c0-5.5,3.2-13.2,7.1-17.1l45.4-45.4c3.9-3.9,10.3-3.9,14.1,0l45.6,45.6c3.9,3.9,10.3,3.9,14.1,0l82.7-82.7"/> </g>

パスを分割するのが真っ当な感じはするんですが、illustrator経由でSVG出力している都合上、パス分割すると管理が面倒になるのでちょっと避けたいなと。

パス分割が真っ当だけど管理上難しいので、d属性を解析して、色を変えたパスをもいっこ作る方向で検討してる。結構面倒。

— Hashimoto Naoki (@hashcc)

2014, 3月 25

@hail2u_さんからコメントいただいたのでSVGグラデーションでなんとかできないか考えてみる。

@hail2u_ どうもです、後ほどためしてみます!

— Hashimoto Naoki (@hashcc)

2014, 3月 25

試してみると、グラデーションがパスに沿ってかかっているわけではなく、パスを囲む矩形をグラデーション領域として掛かるようになっているようです。なので、こういう図形だとオッケーなのですが、

こういう複雑な図形だとダメっぽい(後付で条件出してすみません)

パターンを背景に使うのも、パターンをプログラマブルに出力するとしても結構大変そう。

@hashcc パターンを使えばできないわけではないと思いますが、パスの形にあわせてパターンを作るので編集が手間になりますね…

— Takeshi Kurosawa (@Takenspc)

2014, 3月 26

と悩んでいたらナイスなアイデアをいただく。

@hashcc @hail2u_ http://t.co/ttTGXixtlI んーとこんな?

— DEFGHI1977 (@DEFGHI1977)

2014, 3月 27

SVG勉強不足で知らなかったんですけど、use要素という要素の複製をするものがあるんですね。これに任意の幅間隔の破線をつけられるstroke-dasharray属性を使って、1色ごとに線をつけるというアイデアのようです

ということで、やってみたらできました!

<defs> <path id="test" fill="none" stroke-width="15" stroke-linecap="round" stroke-miterlimit="10" d="M53.888,265.148V193.4 c0-5.5,3.182-13.183,7.071-17.071l45.363-45.363c3.889-3.889,10.253-3.889,14.143,0l45.554,45.554 c3.89,3.891,10.252,3.891,14.143,0l82.661-82.663l-43.34-43.34H53.888"/> </defs> <use xlink:href="#test" stroke="#C30D23" stroke-dasharray="0,150,500,0"/> <use xlink:href="#test" stroke="#CCCCCC" stroke-dasharray="150,500"/>

上記はSVGファイル自体を編集してますが、実際はDOMで動的に運休区間を規定すると思うので、ちょっと方法を変更。

$(document).ready(function () { $("svg > g").wrap("<defs>"); $("svg > defs").after( createPartialPathNode("#c30d23", "0,160,500,0", "test"), ); $("svg > defs").after(createPartialPathNode("#cccccc", "160,500", "test")); function createPartialPathNode(strokeColor, strokeDashArray, href) { var svgns = "https://www.w3.org/2000/svg"; var xlinkns = "https://www.w3.org/1999/xlink"; var use_node = document.createElementNS(svgns, "use"); use_node.setAttribute("stroke", strokeColor); use_node.setAttribute("stroke-dasharray", strokeDashArray); use_node.setAttributeNS(xlinkns, "href", "#" + href); return use_node; } });

ありがとうございましたー!