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

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

#SVG で スクラッチくじ を作ってみた

この記事は、SVG Advent Calendar 2016 の3日目の記事です。

SVG Advent Calendar には、このような記事も過去に投稿しています。


さて。
年末ということで、宝くじ や 占い、それに類するものに興味をお持ちの方も多いかと思います。私自身はそのようなものは好きではないのですが、くじ等を作る側(射幸心を煽る側)の人間として各種法令を遵守しながら立ち回ることは嫌いではありません。ここでは、くじを作る側の人間として、SVGでスクラッチくじを作る手法を紹介したいと思います。

まずは完成品のご紹介

さすがにブログ記事の中でJavaScriptを動作させるのはどうなんや…ということで、別のサイトにHTMLファイルを置くという形でご紹介いたします。
f:id:t_motooka:20161127134448p:plain
https://www.tmotooka.com/svg_scratch.html
このページにアクセスすると、銀色(実態は灰色ですが)の部分をマウス操作やタッチ操作で削ることができ、削ると隠されていたメッセージが表示されます。
「もう一度 くじ を引く」ボタンを押すと、銀色の覆いは元に戻り、中のメッセージはランダムで切り替わります。

こすったときに何が起きているのか?

まず初めに、SVG画像としては、銀色の覆いの向こう側には、あとで表示されることになるはずのテキストのメッセージが描かれています。その手前のレイヤに、銀色の長方形が描かれています。

JavaScript のコードでは mousedown mousemove touchstart touchmove などのイベントを捕捉し、マウスカーソルの位置やタッチ位置を把握しています。
その動いた軌跡を、ある程度の太さの線分で結び、その線分で描かれた領域だけ銀色の覆いが非表示にする、ということを mask という機能を使って実現しています。

mask とは

SVGで描かれている内容のうち、指定した領域を透明にすることができます。領域は、<mask>で囲まれた内側で、通常のSVGと同じように描くことで指定することができます。白く塗り潰された領域は描画され、黒く塗り潰された領域は透明になります。
mask の適用先では mask="url(#{mask要素のid})" という形で適用するべきマスクを指定します。

詳細な説明は、こちら。
Clipping, Masking and Compositing – SVG 1.1 (Second Edition)

銀色の覆いをカスタマイズしてみる

クラッチの仕組みは、くじではなくプリペイドカードなどにおいても頻繁に用いられます。そのようなものの中には銀色の覆いに対して模様を描いていることもあります。
今回紹介したスクラッチくじでも、そのような模様を描くことが可能ですし、実は少し修正するだけで模様を登場させることが可能です。
f:id:t_motooka:20161127142717p:plain
ソースの中に path id="wave" と書かれた部分があると思います。この要素の stroke="none"stroke="#000000" に変えることで、3本の黒い波線を表示させることが可能です。この path はmask適用している <g> タグの内側に居ますので、削る操作をしたとき、銀色の覆いと一緒に削れていきます。

何故これを作ったのか?

今年の8月に、名古屋のWeb界隈の皆様の集まり「WCAN」主催のイベント「WCAN mini 2016 Vol.2 SVG Maniax in NAGOYA」に参加してきました。
wcan.jp
このときの参加レポート: 名古屋のSVGイベントに参加してきました - 職業プログラマの休日出勤

参加レポートには書いていませんが、この懇親会においてどなたかが「SVGでスクラッチくじとか作れたら面白そうだよね」という発言をされていました。このとき私は十分な量のお酒を頂いていたので誰の発言だったのかを思い出すことができないのですが、ここで私は「実装するぞ!」という宣言をしたことだけは覚えています。それから忙しい日々が過ぎる中で「早く SVGクラッチくじ を作りたい」という想いは募る一方でした。

このときの約束を果たすことができて、私は幸せです。

さいごに

紹介した SVGクラッチくじ はMITライセンスにて利用許諾しています。皆さんも、許諾の範囲内でこれを生かし、世界中の多くの人を楽しませるような くじ を作って下さい。
楽しみにしています!