htmlとjsで1歳の子供が遊べるおもちゃを作った話

背景

最近、僕がリビングでPCを触っていると1歳3ヶ月になる子供がキーボードを的確に押してきて作業の邪魔をするようになった。
PCに興味を持つのはいいんだけど、子供がキーを押すと僕の作業の効率が著しく落ちる割に、「エディタ画面で文字がいくつか増える」っていう体験から子供が受ける刺激があんま大したことないのが気に入らなかった。そもそもたぶん僕のまねをするのが嬉しいだけで文字が増えてるの気づいてないし。
そこで、子供のランダムなキータイプに対してちょっと面白げな反応が返ってくるおもちゃをHTMLとJavaScriptで作ってみた。

ちなみに年初にエンジニアからコンサルタントに転身して半年ぐらい全然コード書いてなかったんだけど、以前なら30分ぐらいでできてたぐらいのものを作るのに2時間かかった。。
定期的になにか作らねば作り方忘れてしまうね。

成果物

f:id:miyataro32:20190711214915g:plain

  • キーを押すたびにパステルカラーの●▲■がランダムに画面上に出る
  • 数字キーを押すと図形が押した数字分一気に出る
  • エンターキーまたはスペースキーの押下でア○パンマンかバイキ○マンが出る

github.com

一応作り方

全くたいしたことないけど一応作り方など。

現役時代はvue勉強してたんだけど、めんどかったのでjquery使った。

図形

図形は全部div要素で作りました。大きさと色はランダムにしたかったので%color%とか%size%とかしてあとから置き換えた。
triangleは正三角形にしたかったのでstyle属性の中でcalcで√3掛けたりして計算してる。

const shapes = {
    circle: '<div class="shape circle" style="width: %size%px;height: %size%px;border-radius:50%;background: %color%;" />',
    rectangle: '<div class="shape rectangle" style="width: %size%px;height: %size%px;background: %color%;" />',
    triangle: '<div class="shape triangle" style="border-color: transparent transparent %color% transparent;border-style: solid;border-width: 0 calc(%size%px / 2) calc(%size%px * 1.7320508 / 2) calc(%size%px / 2);height: 0;width: 0;" />'
};

図形の描画

こんな感じの関数を作って引数にランダムな色やらサイズやらを入れて描画している。

const objectDrawer = {};
objectDrawer.drawShapeWithDom = function (shape, size, color, position_x, position_y) {
    let obj = $(shapes[shape].replace(/%color%/g, color).replace(/%size%/g, size))
        .css('left', 'calc(' + position_x + '% - ' + size / 2 + 'px)')
        .css('top', 'calc(' + position_y + '% - ' + size / 2 + 'px)')
        .css('position', 'absolute')
        .appendTo($('body'))
        .show()
        .fadeOut(3000);
    window.setTimeout(() => obj.remove(), 3000);
};

jqueryfadeOutを使って消えるようにしてみた。
fadeOutしてもDOMが残り続けるのが嫌だったのでsetTimeoutでfadeOutしたあとのDOMは消してます。

キーイベントとの紐づけ

普通にonkeypressでランダムな図形かア○パンマン表示するだけ。

(少なくとも)Chromeだとキーを押しっぱなしにすると連続してkeypressとkeydownイベントが発火するみたいだったので、一回のキー押下では一回しか図形が出ないようにkeyIsBeingPressedという変数で押しっぱなしかどうか判断するようにしてみた。

let keyIsBeignPressed = false;
window.onkeypress = function (e) {
    if (keyIsBeignPressed) {
        return;
    } else {
        keyIsBeignPressed = true;
    }
    switch (e.code) {
        case 'Enter':
        case 'Space':
            objectDrawer.drawAnpanman();
            break;
        default:
            if (/Digit|Numpad/.test(e.code)) {
                objectDrawer.drawRandomShapes(e.code.replace(/Digit|Numpad/, ''));
            } else {
                objectDrawer.drawRandomShape();
            }
    }
    console.log(e.code);
};
window.onkeyup = function (e) {
    keyIsBeignPressed = false;
};

最後に

まだユーザ試行をやっていないので、今週末辺りにエンドユーザに触ってもらって、あーとかうーとかいうフィードバックを貰おうかと思っています。
平日の僕が帰る時間にはエンドユーザが寝てるので。
ユーザに喜んでもらえるように継続的にギミック仕込んで改良していく予定です。

なんだか初心者が初めてjs書いてみましたみたいな感じになってるけど、実は俺初心者じゃないんだぜ。。。
そのうち生活の役に立つでかめのアプリを真面目に作る予定です。構想だけはあります。