仕事でSVGを使っているときに、「点線の点の形を自由に変えたい!」「もっと色んな点線を描きたい」と思い、いろいろ考えた結果、それを実現する方法を見つけました。
すでに広く知られていることかもしれませんが、ぱっと情報は見つからなかったので、ここに書いておくことにします。
line 要素をつかって点線を書く
まずは line
要素をつかって点線を書いてみましょう。line
要素はSVGで直線を描画するための要素になります。最初に長さ200pxの直線を書いてみます。
<svg width="320" height="320"> <line x1="50" y1="50" x2="250" y2="50" stroke="black" stroke-width="4"/> </svg>
次に stroke-dasharray
属性を使ってこの直線を点線にしてみます。
<svg width="320" height="320"> <line x1="50" y1="50" x2="250" y2="50" stroke="black" stroke-width="4" stroke-dasharray="4 10"/> </svg>
stroke-dasharray
属性の1つ目の数字は「線を描画する区間の長さ」、2つ目の数字は「線を描画しない区間の長さ」を表しています。「4 10」だと、まず4pxだけ直線を描画して、次の10pxは直線を描画しない、というのを繰り返すことになります。結果として点線を描画することができますね。
でも、line
要素だとできるのはここまで。点の形を変えるには別の方法が必要になります。
path 要素を使って点が三角形の点線を書く
では path
要素を使って点線を書いてみましょう。path
要素は直線や曲線を組み合わせた図形を描画するための要素になります。五角形や星形、楕円なんかを描画するときに使いますね。
では、先ほど描画したものと同じくらいの長さの直線を描画します。
<svg width="320" height="320"> <path d="M 50 50 L 65 50 L 80 50 L 95 50 L 110 50 L 125 50 L 140 50 L 155 50 L 170 50 L 185 50 L 200 50 L 215 50 L 230 50 L 245 50" stroke="black" stroke-width="4"/> </svg>
なにやら、d
属性にとても長い値が指定されています。 この d
属性は path
要素でどのような図形を描画するかを指定する属性になります。詳しくは省きますが、上の例では長さ15pxの直線を13個並べて一つの直線を描画しています。なぜわざわざこんなことをするのか、それはあとのお楽しみ。
では次に、今回の鍵となる marker
要素を定義してみましょう。
<svg width="320" height="320"> <defs> <marker id="triangle" viewBox="0 0 10 10" refY="5" markerWidth="1" markerHeight="1"> <path d="M 0 0 L 10 5 L 0 10 z" /> </marker> </defs> <path d="M 50 50 L 65 50 L 80 50 L 95 50 L 110 50 L 125 50 L 140 50 L 155 50 L 170 50 L 185 50 L 200 50 L 215 50 L 230 50 L 245 50" marker-start="url(#triangle)" marker-mid="url(#triangle)" marker-end="url(#triangle)" stroke="black" stroke-width="4"/> </svg>
直線の見た目はあまり変わらず。でもまだ焦らずに。
marker
要素は line
要素や path
要素にくっつける、様々な形の「マーカー」を定義するための要素です。三角矢印を描画するときなどに使います。marker
要素の内部にマーカーの実際の形状を定義することができて、ここでは path
要素を使って小さな三角形を定義しています。
さて、マーカーをくっつける場所は3種類から選ぶことができます。
- marker-start: 始点
- marker-end: 終点
- marker-mid: 始点と終点以外の頂点
line
要素で指定できるのは始点と終点のみですが、path
要素だと「始点と終点以外の頂点」を指定することもできます。上のコードでは、これら3つの場所すべてにマーカーを指定しています。
さて、ここでおもむろに直線の色を指定する stroke
属性に none
を指定してみましょう。これで透明の線が描画されることになります。するとこうなります。
<svg width="320" height="320"> <defs> <marker id="triangle" viewBox="0 0 10 10" refY="5" markerWidth="1" markerHeight="1"> <path d="M 0 0 L 10 5 L 0 10 z" /> </marker> </defs> <path d="M 50 50 L 65 50 L 80 50 L 95 50 L 110 50 L 125 50 L 140 50 L 155 50 L 170 50 L 185 50 L 200 50 L 215 50 L 230 50 L 245 50" marker-start="url(#triangle)" marker-mid="url(#triangle)" marker-end="url(#triangle)" stroke="none" stroke-width="4"/> </svg>
なんと、点線の点が三角形の直線が表示されました。
path
要素を使って直線を描画するときに、わざわざ短い直線をたくさん集めて長い直線に見えるようにしていましたが、その理由はここにあります。直線の途切れ目は頂点になるので、 marker-mid
属性で指定したマーカーがその場所に表示されます。その結果、 path
要素の始点、終点、その他の頂点にくっついたマーカーが集まって、点線が描画されているように見えるわけです。
まとめ
marker
要素の中には様々な形を定義できるので、これで点線の点を自由自在に変更することができるようになりました。
ネックになるのは path
要素の d
要素が複雑なこと。この辺りはSVGを手で書くんじゃなくて、SVGを生成してくれるようなツール or プログラムを使うのがよさそうですね。
もっと他にいい方法があれば、ぜひぜひ教えて下さい。
それでは!