はじめに
本稿はSVG Advent Calendar 2015 - Adventarの19日目の記事です。
SVGで特定の図形を描くための最小コード(→コードゴルフ)って考えられているのか、という疑問から始まり、
数学の作図問題のような厳密な記述が可能なのか(どのみち描画段階で丸められるのでしょうが)気になってしまい、ある程度頑張るに至りました。
コードゴルフに役立つTips
-
<svg>
タグの属性は全削り可能 -
<svg>
の閉じタグ(</svg>
)は省略しても動作するが、HTML5の文法には違反(一応HTML的にvalidなものを目指します) - svg要素内の図形要素は閉じタグ不要
- 上述の通り図形要素は閉じタグ不要だが、その場合"/"で終える必要あり(例:
<path d="…" />
)(※要出典) - 属性のダブルクォーテーションは一定の条件下で省略可(※要出典)
- ダブルクォーテーションを省くため、スペースを回避する"+"や","が有用(参考 Thanks @rikuo)
- HTMLに埋め込む際のSVG要素のデフォルトサイズは300px×150px。(参考)
- pathを使うときはHコマンドとVコマンドを使うとかなり短縮できる
- 塗りの場合、pathは最後にZコマンドを付けなくても閉じてくれる
- pathの小文字コマンドは相対指定になり、役立つと思った割には現時点では活躍しなかった
プリミティブな図形
円
<svg><circle cx=55 cy=55 r=55 /></svg>
代替記述
<svg><rect cx=55 cy=55 rx=55 ry=55 width=55 height=55 /></svg>
楕円
<svg><ellipse cx=89 cy=55 rx=89 ry=55 /></svg>
長方形
<svg><path d=M0,0H89V55H0 /></svg>
代替記述
<svg><rect width=89 height=55 /></svg>
↑ <rect>
は短く書けそうでいて、<path>
には及びませんでした。
<svg><path d="M0,0L89,0L89,55L0,55Z" /></svg>
↑ H
コマンドとV
コマンドを使わないとこれだけ長くなってしまいます。
菱型
<svg><path d=M0,34L34,0L68,34L34,68 /></svg>
線分
線分といってもrect
要素なのでちょっと頓智ではありますが。
<svg><rect width=89 height=1 /></svg>
代替記述
こっちなら正しい線分ですが、
これらの描き方だとy座標が0なので水平線の上半分がなくなってしまいます。
<svg><line x2=89 y2=0 stroke=red /></svg>
<svg><path d=M0,0H89 stroke=red /></svg>
放物線
<svg><path d=M0,0Q17,55+34,0 stroke=red fill=none /></svg>
今回のプリミティブな図形の中では変わりダネですが、貴重な厳密解です。
stroke
属性とfill
属性は避けられませんでしたが、色指定を申し訳程度にred
(他に3文字の色は"tan"のみ?)として削っています。
正多角形(近似)
正3角形
<svg><path d=M0,0H52L26,45 /></svg>
正4角形(正方形)
これは厳密な描画が可能なので、後述を参照してください。
正5角形
<svg><path d=M0,77V18L56,0L90,48L56,95 /></svg>
今回気合が足りず、手抜きです。
正多角形(厳密)
正3角形
今回のヤマです。(無理数を座標指定することが不可能と判断し、3次元の変形をするに至りました。)
<svg><path d=M0,0H68L34,68 style=transform:rotateX(30deg) /></svg>
解説
厳密に正3角形を書くためには無理数の座標指定か無理数のscaleをかけるなど、
SVGの文法で不可能な方法しかありません。
calcを使っても平方根は求められません。
それを克服するために3D変形を使ってみました。
底辺2、高さ2の3角形を平行投影で30度奥に傾ければ、高さ(=2)に相当する辺は見た目として高さ√3に縮小されます。
transform属性に3D指定ができるのはSVG2以降のようです(まだ草案)。
SVG Transforms 1.0, Part 2: Language
Coordinate Systems, Transformations and Units — SVG 2
モダンブラウザーではWebKitのみ、CSSのtransformプロパティにまだベンダープレフィックスが必要な環境がありますが、いずれなくなることを期待してベンダープレフィックスは付けませんでした。
参考:
ベンダーprefix(-webkit/-moz/-o/-ms)の要否まとめ 2015/6 [無料ホームページ作成クラウドサービス まめわざ]
正4角形(正方形)
<svg><path d=M0,0H89V89H0 /></svg>
テクニックは長方形の時と同様です。
代替記述
<svg><rect width=89 height=89 /></svg>
↑ 長方形のとき同様、<rect>
は短く書けそうでいて、<path>
には及びませんでした。
<svg><path d="M0,0L89,0L89,89L0,89Z" /></svg>
↑ 長方形のとき同様、H
コマンドとV
コマンドを使わないとこれだけ長くなってしまいます。
正5角形
今回気合が足りず、未解決です。
描画可能ではあると予想しています。
正6角形
これも描画可能ではあると予想しています。
正7角形
これはもしかしたら不可能なのでは?と思っています。
最後に
上述のコードゴルフより短いコード、
正5角形、または特に正7角形の厳密描画、
その他有用な図形の描画等、コメントor DMお待ちしています。