HTML5 LogoをCanvasで描いてみた


かっこ良いんだか悪いんだか、ちょっとわからないけど、HTML5のロゴができたということなので、ちょっと遊んでみた。CCライセンスで提供されている。SVGデータもあるので、中身を見たところ、これならすぐにCavnasでも描けそうだと思い立ったので、帰宅電車の中でコードを書いてみた(はい、お気楽モードです)。


polygonは下記のように頂点の並びpointsと塗りつぶす色を指定しているだけ。

<polygon fill="hsl(13, 77%, 52%)"
         points="107.644,470.877 74.633,100.62 437.367,100.62 404.321,470.819 255.778,512 "/>

pointsを正規表現でパースするのが実装が簡単。一度に全部分解するのもいいけど、gオプションで有効なlastIndex機構を使って前から順番にパースする。以下のようなコードになる。forの使い方にちょっと抵抗を感じる人もいるかもしれない。

var pat = /(-?\d+(\.\d+)?)\s*,\s*(-?\d+(\.\d+)?)/g;
g.beginPath();
for (var p, head = true; (p = pat.exec(points)); ) {
   var x = Number(p[1]);
   var y = Number(p[3]);
   if (head) {
     g.moveTo(x, y);
     head = false;
   ] else {
     g.lineTo(x, y);
   }
}
g.close();
g.fill();


次に、pathは下記のように相対/絶対座標と垂直/水平直線だけを使っている。大文字は絶対座標で、小文字が相対座標。Mは始点(moveTo), Hは水平直線、Vは垂直直線。

<path d="M108.382,0h23.077v22.8h21.11V0h23.078v69.044H152.57v-23.12h-21.11v23.12h-23.077V0z"/>

polygonの正規表現よりちょっと複雑だけど、大したことはない。Canvasには相対位置指定のlineToがないので、現在の(x, y)座標を変数に保持している。以下のようなコードになる。

var pat = /([MLVHZ])(\s*(-?\d+(\.\d+)?)(,|\s+)?(-?\d+(\.\d+)?)?)?/ig;
var x = 0;
var y = 0;
g.beginPath();
for (var p; (p = pat.exec(path)); ) {
  switch (p[1]) {
  case 'M':
    x = Number(p[3]);
    y = Number(p[6]);
    g.moveTo(x, y);
    break;
  case 'v':
    y += Number(p[3]);
    g.lineTo(x, y);
    break;
  case 'H':
    x = Number(p[3]);
    g.lineTo(x, y);
    break;
      :
     (略)
      :
  case 'z':
    g.closePath();
    break;
  }
}
g.fill();



こうしてできたのが、左の画面。単に表示してもつまらないので、くるくる回転伸縮アニメーションをつけた。

コードと実際の動作は、こちらからどうぞ:

気晴らしにSVGそのものからCanvasに描画するコードを書くのも面白いかもしれない。

Have fun!