接続端末が同期して光るサイリウムみたいなWebアプリをつくった
やったこと
年末に宴会芸みたいなものをやることになり色々と何をやろうかと話し合っていたのですが、どうにもオモシロな方向に振り切れなさそうだね〜となり、エンタメ方向なことをやりました。具体的には、
- 数名が舞台で踊る
- 観客には、あるサイトにスマホでアクセスしてもらう
- 1名(オレ)がスタートボタンを押して、サイトの背景色が次々と変化する
- 会場の全端末の画面色が同期する(はず)
- サイリウムみたいに振ってもらう
- 一体感ヤバイ
という算段でした。で、自分の役割としてサイトの制作が割り当てられたというわけです。つくったサイトは以下。
- アクセスしてもらうURL: https://flash-light.herokuapp.com
- 操作数する1名が使う操作画面: https://flash-light.herokuapp.com/controller
前者のURLを複数ウィンドウで開いて、後者画面のテーブル1行目をクリックすると、何かが始まります。 元々公開するつもりも無かったり、急いでいたり手戻りがあったりでコミットログは酷いですが、コードは https://github.com/Joe-noh/flash に置いておきます。
内部
要素技術
内部実装
+-------+ | Flash | +-------+ | +---------------+ | Flash.Manager | <- 光らせ方パターンを知っている +---------------+ | +---------------+ | Flash.Maestro | <- 生まれるときにパターンを教えてもらい、クライアントへ指示を送る +---------------+
最初に、起動時の処理について説明します。まずPhoenixアプリの一部としてFlash.Manager
がぶら下がります。Flash.Manager
は、スタートするときにFlash.Maestro
をつくり、そのPIDを状態としてキープします。ただし、ここで生まれたFlash.Maestro
は「画面を黒にしろ」というパターンしか教えてもらえないため、初期画面として画面を真っ黒にする働きしかしません。Flash.Maestro
は状態として現在の光らせ方パターンを持っていて、途中から新たに接続してきた端末にはそのパターンを指示として送るため、まだ操作画面でなにもしていない状態では、観客用画面は黒になります。
次に、操作画面にアクセスすると、あらかじめ定義されたサーバから光らせ方のパターンが送られてくるので、それを元に表が作られます。任意の行をクリックすると、サーバにどの行がクリックされたかが送られます。すると、その時点で動いていたFlash.Maestro
が殺され、クリックされたパターン以降の光らせ方パターンを持った、新たなFlash.Maestro
がつくられます。このFlash.Maestro
は先程の画面を真っ黒にするだけのものとは違い、きちんとパターンを渡されるため、クライアント全員に指示を出し、それを受けたクライアントは画面色等を変化させます。
苦労・妥協したとこ
どうしてもしっかり上手くできなかったのは、クライアントを同期させることでした。ここができてないと当初の目的が果たせないのですが、クライアント側のネットワークまでは正直どうしようもありませんでした。同じElixir/Phoenixで、複数端末にWebSocketでプッシュするアプリをつくった方々のブログ記事には、何度か送受信を繰り返しておくと揃うようになったというような謎テクノロジーが書かれていてマジかよと。でも実際に試してみるとそれが一番良かったので、光らせ方の指示を受けたクライアントは、サーバに返事を返すようにしてあります。
ハマったポイントとしては、プロダクション環境でbrunchが吐き出したcssが動作しないことがありました。cssプロパティには、例えばbackground
のように複数の値を取って一気に設定するものと、background-color
やbackground-image
のように1つ1つ設定するものがありますが、brunchから使用していたclean-cssがプロダクション環境ではプロパティのマージを行って1つのbackground
にまとめるようで、これがInvalidなcssを生み出していたのでした。対策として、brunch-config.js
にこの設定を追加しました。
妥協した点としては、光らせ方パターンをコンパイル時に生成してパフォーマンスを上げようとしたのですが、マクロでハマって時間がかかりそうだったことと、ランタイムにその都度生成しても特に遅いと感じなかったため、見送りました。
感想
なんとか本番で動いて、すごいという感想を頂けたのでまぁ良かったかなと思います。想定外だったこととして、ステージで踊る人がいると皆スマホで写真やビデオを撮りたくなってしまうため、あんまりURLを開いてくれてないっぽかったです。でも主役は踊る人たちであって、自分のは踊りがあってこその演出の一部なので、それはそれでよいのかなと思いました。
ハー、年の瀬。