職業プログラマの休日出勤

職業プログラマによる日曜自宅プログラミングや思考実験の成果たち。リアル休日出勤が発生すると更新が滞りがちになる。記事の内容は個人の意見であり、所属している(いた)組織の意見ではない。

手入力のSVGでクリスマスツリーを描こう☆

この記事は SVG Advent Calendar 2014 の24日目の記事です。前の日は SVG画像にRDFでメタ情報を記述する:CCライセンスや派生元作品など - 聴く耳を持たない(片方しか) でした。

このアドベントカレンダー、途中で飛んでしまっている箇所もありましたが、いよいよ千秋楽に突入しようとしております。皆さん、これまでに登場したSVGの技術、一通り試されましたでしょうか? 楽しいものから役に立つもの、そして私達の人生の質を変えてくれるものまで、本当に様々な記事が投稿されましたね。

さて、この記事では、クリスマスツリーを手入力のSVGで描いてみたいと思います。例によって本文にはSVGのコードが表示されますが、ここまでSVGアドベントカレンダーを書いたり読んだりしてきた皆さんなら、心のキャンバスにSVGレンダリングさせることができますよね?
ちょっと練習してみましょうか。

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="320" height="240" viewBox="0 0 320 240">
	<rect stroke="none" fill="#202030" x="0" y="0" width="320" height="240"/>
</svg>

そう、そうです、心の眼でSVGのタグを見つめるのです…。
暗い未来、もとい、暗い矩形が見えてきました? いい調子ですね!!

皆さんが本気で心眼を使うのなら、私だって本気でSVGタグを打ち込みましょう。
下書き無しのぶっつけ本番です!!
クリスマスイブの日、午後10時過ぎに書き始めました。日付が変わるまでに公開できるかな??
この段落の時点で10時20分です。ちょっと不安ですが…

キャンバス

クリスマスツリーを描く訳ですから、当然、縦長のキャンバスを用意しないといけませんね。
私の心の中にあるクリスマスツリーは、縦横比が 2:1 です。
幅は300px程度にしておくと幸せになれる気がしてるので、ここでは横幅300px, 高さ600pxとしておきましょう。簡単にするために、viewBoxの幅と高さも同じにしておきましょうか。
ついでに、背景も描きましょう。背景は銀世界、 #f0f0f3 くらいの色が良いですかね。

ここまで登場した話からSVGを書くと、次のようになります。

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="300" height="600" viewBox="0 0 300 600">
	<rect stroke="none" fill="#f0f0f3" x="0" y="0" width="300" height="600"/>
</svg>

まだ殺風景ですね。でも、これから良いツリーになりますよ、きっと!!

葉っぱの部分やら電飾やらがクリスマスツリーの根幹であると思い込んでいる人は多いかもしれませんが、それは大きな間違いです。クリスマスツリーの根幹をなすのは、文字通り幹なのです。
どっしりと構えるような形状にしつつ、上にいくほど細くなるように3次のベジェ曲線を描きましょう。3次のベジェ曲線と言えば、path の C コマンドですね。
木の幹の色、明度はそんなに高くなく、赤が一番強くて、緑がその次に強い、という色にすると良い感じがしますね。ここでは #806030 としておきましょう。

こうなります。

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="300" height="600" viewBox="0 0 300 600">
	<rect stroke="none" fill="#f0f0f3" x="0" y="0" width="300" height="600"/>
	<path stroke="none" fill="#806030" d="M120,590 C120,400 120,180 150,180 C180,180 180,400 180,590 Z"/>
</svg>

卑猥なものに見えてしまった皆さんの心は、汚れています。

葉っぱ

流石にこの短時間では1枚1枚書くのも難しいので、大雑把に書いてしまいましょう。
色は、木の幹と同様に明度はそれほど高くなく、緑にちょっと青を足しただけの色にしましょうか。 #207a4c くらいがいいですね。
形は、基本的には三角形なんですが、頂点は尖らせずに、円弧を用いて丸みを持たせるのが良いですね。円弧と言えば、path の A コマンドを使うのが良いですね。

こうなります。

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="300" height="600" viewBox="0 0 300 600">
	<rect stroke="none" fill="#f0f0f3" x="0" y="0" width="300" height="600"/>
	<path stroke="none" fill="#806030" d="M120,590 C120,400 120,180 150,180 C180,180 180,400 180,590 Z"/>
	<path stroke="none" fill="#207a4c" d="M20,570 A10,10 0 0 0 20,580 H280 A10,10 0 0 0 280,570 L155,140 A7,7 0 0 0 145,140 Z"/>
</svg>

なかなか良いツリーっぽくなってきましたね!!!!!1111

装飾

これだと単なる木ですので、クリスマスらしい装飾を施したいと思います。装飾なので、ちりばめたいですよね?そんなときに使うのが use タグです。部品の再利用ができるんですよ!!

装飾の構成要素は、★印にしましょうか。 use タグを使う際には平行移動させるので、簡単にするために、座標平面の原点を中心とする半径10の円周上の、0°、72°、144°、216°、288°、の5点を上手い具合につないで★印にしましょう。そんなに適当に線を引いても★印作れるの?と思ったあなた、fill-rule の仕様 を眺めておいてくださいね。

さすがに三角関数を暗算するほどには感覚が研ぎ澄まされているとは言い難く、計算はGoogle先生にお願いすることにしましょう。「sin 144deg」で検索すると度数法で三角関数の計算をしてくれるんですよ。知ってました?
色は黄色、 #ffff60 くらいがいいですね。
あとは、 use タグを使う際に xlink 名前空間を使う必要があるので、名前空間の宣言も svg タグに加えておく必要がありますね。

こうなります。

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300" height="600" viewBox="0 0 300 600">
	<rect stroke="none" fill="#f0f0f3" x="0" y="0" width="300" height="600"/>
	<path stroke="none" fill="#806030" d="M120,590 C120,400 120,180 150,180 C180,180 180,400 180,590 Z"/>
	<path stroke="none" fill="#207a4c" d="M20,570 A10,10 0 0 0 20,580 H280 A10,10 0 0 0 280,570 L155,140 A7,7 0 0 0 145,140 Z"/>
	<defs>
		<path id="christmas-star" stroke="none" fill="#ffff80" d="M10,0 L-8.09,5.88 L3.09,-9.51 L3.09,9.51 L-8.09,-5.88 Z"/>
	</defs>
	<use xlink:href="#christmas-star" transform="translate(180, 50)"/>
	<use xlink:href="#christmas-star" transform="translate(100,100)"/>
	<use xlink:href="#christmas-star" transform="translate(220,150)"/>
	<use xlink:href="#christmas-star" transform="translate(270,200)"/>
	<use xlink:href="#christmas-star" transform="translate(170,250)"/>
	<use xlink:href="#christmas-star" transform="translate(150,300)"/>
	<use xlink:href="#christmas-star" transform="translate(100,350)"/>
	<use xlink:href="#christmas-star" transform="translate(210,400)"/>
	<use xlink:href="#christmas-star" transform="translate( 70,450)"/>
	<use xlink:href="#christmas-star" transform="translate(230,500)"/>
	<use xlink:href="#christmas-star" transform="translate(180,550)"/>
</svg>

描いた結果

さあ、ここまでタグを手打ちしてきた結果、皆さんの心のキャンバスには美しいクリスマスツリーが描かれていますか?
ここらへんで、答え合わせをしておきましょうかね。
答えは、こうですよ!

リア充爆発


おや、クリスマスツリーの中央に、何か黒くて小さな汚れが見えますね…。
もしかして、私の心が汚れているだけなのでしょうか?
皆さんには、見えますか??