調べて分かる道具箱

図形を描いてSVGで書き出す

数を入れると図のほうが変わる学びのページは図形の面積と体積です。 こちらは自分で図を組んで、SVGのコードを持ち帰る道具です。 面積や体積は出しません。

いま置いてある図形の見本
白い地と方眼は見るための目安で、コードには入りません(SVG の地は透明です)。図の上を押すと、その場所の数がx と y の欄に入ります。

図形を足す

どの図形にしますか
四角の数(そのまま <rect> の属性になります)
x(左はし)y(上はし)width(よこの長さ)height(たての長さ)
塗り(fill)
線(stroke)
stroke-width(線の太さ)0 で線なし

置いた図形

下にある図形ほど、あとから描かれます。SVG に重なりの番号(z-index)はなく、あとに書いたものが上になります。だから↑↓で順番を入れかえます。

  1. 四角/x 40/y 40/width 160/height 100/塗り #dbe8ff/線 #0017c1 4
  2. 円/cx 230/cy 150/r 60/塗りなし/線 #1a1a1a 6

SVG のコード

このまま HTML に貼れます。え.svg のような名前で保存しても、そのまま開けます。

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 240">
  <rect x="40" y="40" width="160" height="100" fill="#dbe8ff" stroke="#0017c1" stroke-width="4" />
  <circle cx="230" cy="150" r="60" fill="none" stroke="#1a1a1a" stroke-width="6" />
</svg>

長い行は、この枠の中だけ横に動かせます(キーボードでも動きます)。全部で252文字です。これが絵の全部で、 画像のファイルは1つも要りません。

よくある質問

SVGは写真の画像と何が違うのですか?

写真の画像(PNGやJPEG)は点の色をならべたもので、320×240の絵なら76,800個の点の色を持ちます。SVGはそうではなく、「ここに円を描く」「ここからここへ線を引く」という命令を文字で書いたものです。だから拡大しても粗くならず、文字なので検索も、どこが変わったかの差分も取れます。反対に、風景写真のように細かい色が続くものには向きません。

viewBoxはどんな意味ですか?

min-x、min-y、幅、高さの4つの数で、絵の中の座標系を決めるものです。W3Cの仕様では「利用者空間の長方形を、SVGのビューポートの境界に対応づける」と説明されています。表示する大きさとは別なので、同じ絵を100ピクセルでも1000ピクセルでも同じ形のまま出せます。左上が原点で、xは右へ、yは下へ増えます。算数のグラフとは上下が逆です。

幅(width)を書かなくてもいいのですか?

書かなくても大丈夫です。SVG2は、いちばん外側のsvg要素のwidthとheightの計算値がautoのときは100%と同じに扱う、と定めています。つまり幅を書かなければ、貼った先の入れ物いっぱいに広がります。大きさを決めたいときは、貼ったあとにCSSのwidthで決めるほうが扱いやすくなります。

塗りたくないのでfillを消したら、真っ黒になりました。

fillの初期値がblack(黒)だからです。書かないことは「塗らない」ではなく「黒で塗る」になります。塗らないときはfill="none"と書きます。逆にstroke(線)の初期値はnoneなので、線は書かなければ出ません。stroke-widthの初期値は1です。この道具は塗らないときにfill="none"を必ず書き出します。

図形の重なりの順番はどう決まりますか?

書いた順です。仕様は「最初の要素が先に塗られ、あとの要素がその上に塗られる」と定めていて、CSSのz-indexのような番号はありません。画家が下の色から順に塗るのと同じなので、painters model(画家のモデル)と呼ばれます。この道具の↑↓のボタンは、コードの行そのものを入れかえています。

半径や幅に0やマイナスを入れるとどうなりますか?

0にすると、その図形は描かれません。仕様が「どちらかの寸法の計算値が0なら、その要素の描画を無効にする」と定めているためです。マイナスは「読み取りの誤り」として無視されます。だからこの道具は大きさにマイナスを受け取らず、0を入れたときは「描かれません」と画面に理由を出します。

xmlnsは必要ですか?

HTMLの中に直接貼るだけなら要りません。HTMLの読み取り側がSVGの名前空間を付けてくれるからです。ただし.svgというファイルにして保存したり、XMLとして読ませたりするときは必要になります。どちらでも困らないように、この道具はxmlnsを付けて書き出します。値は書き出したコードの1行目に出ています。

四角・円・三角・線を数で置いて、そのまま貼れるSVGのコードにします。 マウスが使えなくても、キーボードだけで最後まで作れます。

SVGは「絵」ではなく「命令の並び」です

いちばん大事なところです。SVGは絵ではありません。「ここに円を描け」「ここからここへ線を引け」という命令を文字で書いたものです。

たとえば円は、cx(中心のよこ)・cy(中心のたて)・r(半径)の3つだけで決まります。 コードにすると<circle cx="230" cy="150" r="60" />── これで円1つが完全に決まります。

点の色をならべる画像だと、こうはいきません。 このページの見本と同じ320×240の大きさなら、点は76,800個あって、 その1つずつに色が要ります。数十文字で書けるものに、何万個ぶんの色を持たせていることになります。

文字であることの得は、大きさだけではありません。中の言葉で検索できる、どこが変わったかを1行ずつ見比べられる、あとから手で書き直せる── 絵のファイルではできないことが、ぜんぶできます。

viewBoxは「絵の中の座標系」で、表示する大きさとは別です

viewBox="0 0 320 240"の4つの数は、左からmin-x・min-y・幅・高さです。 これは絵の中だけで通じる目もりで、画面に何ピクセルで出すかとは別のものです。

だから同じコードを、小さくても大きくても同じ形のまま出せます。拡大しても粗くならないのはこのためです。 書き出すコードに幅と高さをわざと書いていないのも同じ理由で、 書かなければ貼った先の入れ物いっぱいに広がります。

ひとつ気をつけるところがあります。yは下に向かって増えます。算数のグラフは上へ行くほどyが大きくなりますが、SVGでは左上が(0, 0)で、下へ行くほどyが大きくなります。 上の見本で三角形のてっぺんを高くすると、数のうえではy が小さいほうへ動きます。

あとに書いたものが、上に重なります

SVGには重なりの番号がありません。 決めているのは書いた順番だけで、先に書いたものが先に塗られ、あとのものがその上に塗られます。

絵の具で塗るのと同じ考え方なので、画家のモデル(painters model)と呼ばれています。 だからこの道具の一覧では、下にある行ほど手前に出ます。 ↑↓のボタンは、見た目を動かしているのではなくコードの行そのものを入れかえています。

「塗らない」は、fillを書かないことではありません

ここは必ず1回はつまずくところです。fillの初期値はblack(黒)なので、fillを書かないと黒く塗られます。 塗りたくないときはfill="none"と書く必要があります。

線のほうは逆で、strokeの初期値はnoneです。 書かなければ線は出ません。stroke-widthの初期値は1なので、 太さを書かずに色だけ書くと、細い線が引かれます。

「書かなかったときにどうなるか」は、決まりとして決まっている── これがSVGの読み方のこつです。この道具は、塗らないときにfill="none"を必ず書き出し、線の太さを0にしたときはstrokeごと書きません。

数で置けるようにしたのは、そうしないと使えない人がいるからです

絵を描く道具は、たいていポインタで引っぱって描きます。 けれど、それだけにするとキーボードしか使わない人には、1つも図形が置けません。

WCAG 2.2の達成基準2.1.1(キーボード)は、 すべての機能をキーボードから操作できることを求めていて、 例外は動きの軌跡そのものが意味を持つ場合(手書き文字など)だけです。 図形を置く操作は始まりと終わりの点さえ決まればよいので、 この例外には当たりません。

並べ替えも同じです。2.5.7(ドラッグ動作)が 「ドラッグで行う操作は、ドラッグなしでもできること」を求めているので、 つかんで動かす形にはせず↑↓のボタンにしました。 ポインタで押して座標を拾う近道も付けてありますが、それが無くても全部できます。

決まりの出どころは、図形の属性と viewBox がW3CのSVG 2(新しいタブで開きます)(shapes・coords・painting・structの各章)、重なりの順番がSVG 1.1の3.3 Rendering Order(新しいタブで開きます)、キーボードとドラッグの話がWCAG 2.2(新しいタブで開きます)です。書き出す色は、貼った先で消えないようにCSSの変数ではなく実際の色で書いています。 面積や体積を出したいときは図形の面積と体積へどうぞ。