Jonathan Puckeyが作ったPointer Pointerというサイトがある。話題になったので見た人も多いと思うが、マウスを置くとそこを指差した写真が表示される作品だ。何となく彼のGithubを見ていたら、voronoi-gridというリポジトリがあり、そこにexampleとしてあのサイトの仕組みがわかるコードがあった。
マウスを置くとそこを指で差す写真が表示される、というのは一見単純でくだらないアイディアのようでいて、どう作るかを考えると途方に暮れてしまう。まず思いつくのは画面を等間隔のグリッドで分割し、それぞれに当てはまる写真を撮影する方法だ。しかし、あの質感も含め、無作為に選ばれたような雰囲気は、なかなか意図して出せないだろう。次に考えるのが検索だが、座標に合った位置を指差している写真を探すのはかなり難しい。クラウドソースでひとつひとつお願いして集めるのは可能かも知れないが、これも労力がかかる。
彼の賢さは、これを写真から出発して作り上げたところにある。直接聞いた訳ではないので推測にしかならないが、ソースコードを読み、フォルダ構成を見ればその思考の流れが分かる。
- まず人が指を差している写真を集め、全てのサイズを合わせる。
- Photoshopなどでカーソルを指の位置に合わせて座標を特定し、ファイル名の末尾に付け加える。
- 次に、それを頼りにX座標、Y座標、画像ファイル名をまとめたJavaScriptオブジェクトの配列としてpoints.jsに記録する。
- points.jsからデータを読み出し、X座標とY座標の集合からボロノイ分割を作る。ボロノイ分割は、ある点と点の距離が等しくなる線で領域を分割するアルゴリズムだ。これで「写真の指が差している座標で」分割された領域を作ることができる。
- あとはマウスの位置が分割されたどの領域上にあるかを特定し、その母点の座標を元に該当のファイルを読み出して表示する。
さらに素晴らしいのは、点の増減が簡単にできることだ。新たな写真を追加し、座標を特定してファイル名をつけ、points.jsにオブジェクトを書き込むだけ。指がどこを差していようが関係なく、プログラムを変更することもなく、どんどん追加できる。削除する場合は、points.jsからオブジェクトを消せば良い。ある点が削除されたとしても、アルゴリズムによって再度領域が分割され、別の写真が割り当てられるので、マウスを合わせた時の自然さは保たれる。
これが最初に考えたような等間隔のグリッドだとどうだろう?1枚だけ追加するとか、1枚だけ削除することはできず、分割した行や列単位で増減させないといけない。プログラムの修正も必要になる。
アイディア自体の面白さだけでなく、仕組みもエレガントで、本当にすごい。
※ exampleのコードではpoints.jsは使ってなくて、おそらくgetPoints()の内部にコピー&ペーストしているが、保守性を考えるとpoints.jsを使うのが望ましい。
0 件のコメント:
コメントを投稿