Riot.jsで「日用品残りHPメーター」を作ってみる
カテゴリ:新技術開拓記
こんにちは!inglowの開発担当です。
今回は、前回紹介した「Riot.js」を使って簡単なツールを作ってみました。
Riot.jsの簡単な使い方については、前回の記事を参考にしてください!
▼今キテる?riot.jsを試してみた https://inglow.jp/techblog/js-riotjs/
今回作るもの
今回はこんなデザインのものを作成しようと思います。
この日用品があと残りどれくらいなのかをメモできる簡単なアプリケーションです。
HTMLコーディング~タグ埋め込み
まずは、とりあえずHTMLをコーディングしていきます。
実際にブラウザでみたら、アイテムの追加フォームは上の方が使いやすいかなと思い、上に移動させました。
コーディングする時に、繰り返しになるものや、変数を組み込む位置も意識できるといいです。
コーディングの詳細は所略します。
日用品残りHP
台所洗剤
1 |
次に、動作を組み込みたい部分をテンプレートタグとして読み込みさせます。今回は、というタグ名で作成します。
日用品残りHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<script type="riot/tag"> <itemlist> <div class="add_item"> <input type="text" name="add_item_name" placeholder="アイテム名" /><button><i class="fas fa-plus"></i></button> </div> <div> <div class="item"> <button class="trash"><i class="fas fa-trash"></i></button> <div class="progres"> <p class="bar"></p> <p>台所洗剤</p> <p class="max-min-btn"> <button></button> <button></button> </p> </div> <button class="plus"><i class="fas fa-plus"></i></button> <button class="minus"><i class="fas fa-minus"></i></button> </div> </div> </itemlist> </script> <script type="text/javascript"> //タグの読み込み・宣言よりあとに入れること riot.mount('itemlist'); </script> |
データの準備
テンプレートタグの準備ができたら、埋め込むデータの構造を考えていきます。
このアプリケーションでは、日用品について、「名前」「残りの数値(今回は100%をmaxとした値)」を一つの日用品としてデータを保持したいので、下記のようなデータの構造になります。
とりあえず、入りそうなデータを直接指定して格納して実装をしてみます。
1 2 3 4 5 6 7 8 9 10 |
items = [ { 'name':'台所洗剤', 'hp':90 }, { 'name':'柔軟剤', 'hp':40 }, ]; |
データが準備できたら、次はeachで日用品の配列データが表示できるようにしていきます。
また、残りHPによってバーの色や文字色が変更できるように、バーの色・文字色も動的に指定されるようにデータを追加します。
1 |
<!-- ↓追記 itemの中に{name:'','hp':''}のデータが入る --> |
{item.name}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
items = [ { 'name':'台所洗剤', 'hp':90, 'bk':'#4072B3', //色指定はとりあえず適当でもOK 'clr':'#333', }, { 'name':'柔軟剤', 'hp':40, 'bk':'#4072B3', 'clr':'#333', }, ]; |
各種ボタンの実装
データが準備できたら、次はボタンの実装をしていきます。
まずは、「+」「-」のボタンを実装します。
処理の内容はシンプルで、引数でイベントを取得し、対象itemの「hp」の値を変更しています。
上がり幅・下がり幅を同じにするため、あらかじめ変数で変動値を指定しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<!-- ボタンのonclickで関数を指定する --> <button class="plus"><i class="fas fa-plus"></i></button> <button class="minus"><i class="fas fa-minus"></i></button> this.hp_spn = 5; //変動値 //「+」ボタン addHp(e){ key = e.item.i; v = this.hp_spn; this.items[key]['hp'] += v; } //「-」ボタン defHp(e){ key = e.item.i; v = this.hp_spn * -1; this.items[key]['hp'] += v; } |
この状態で一度ボタンをクリックしてみると、HPバーの長さが変更されると思います。
ですが、このままだと、101以上になるし、0以下になってしまうので、101を超えたら100に、0を下回ったら1になるよう調整する共通の関数を用意します。
また、数値を確認してバーや文字の色を変更する処理も共通の関数に記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
<button class="plus"><i class="fas fa-plus"></i></button> <button class="minus"><i class="fas fa-minus"></i></button> this.hp_spn = 5; //変動値 this.hp_max = 100; this.hp_min = 1; addHp(e){ key = e.item.i; v = this.hp_spn; this.items[key]['hp'] += v; this.changeHpStyle(key); //値を調整する関数を呼び出す } defHp(e){ key = e.item.i; v = this.hp_spn * -1; this.items[key]['hp'] += v; this.changeHpStyle(key); } changeHpStyle(key){ //maxより上・minより下にならないように調整する if(this.items[key]['hp'] > this.hp_max){ this.items[key]['hp'] = this.hp_max; } else if(this.items[key]['hp'] < this.hp_min) { this.items[key]['hp'] = this.hp_min; } //バーと文字の色を変更する this.items[key]['bk'] = '#4072B3'; //デフォルト色 this.items[key]['clr'] = '#fff'; if(this.items[key]['hp'] <= 1){ this.items[key]['bk'] = '#EB8686'; this.items[key]['clr'] = '#CE2937'; } else if(this.items[key]['hp'] < 30) { this.items[key]['bk'] = '#EB8686'; } else if(this.items[key]['hp'] < 50){ this.items[key]['bk'] = '#6088C6'; } //スタイルを変更した場合は、実行する必要がある this.update(); } |
項目を増やす・減らす処理の実装
次に、項目をふやす処理を書いていきます。
テキストフォームに入力したあと、「+」ボタンを押すことで項目を追加します。
また、バーの左にあるゴミ箱ボタンで項目を削除します。
1 |
<!-- それぞれのボタンに関数を指定する --> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
//項目を追加する Array.push()関数を使ってオブジェクトを追加します。 addItem(e){ //inputのnameに「add_item_name」を指定することで、「this.add_item_name」で要素を取得できるようになる push_key = this.items.push({ 'name':this.add_item_name.value, 'hp':100, 'bk':'#6088C6', 'clr':'#333', }); this.add_item_name.value = ''; this.changeHpStyle((push_key - 1)); } //項目を削除する removeItem(e){ this.items.splice(e.item.i, 1); } |
保存機能の実装
ここまでくれば大方完成です!が、今の状態だと、せっかくメモしてもセッション切れなどでブラウザを再読み込みした時にデータがなくなってしまうので、「localStorage」にデータを保存するようにします。
セーブする関数と、データを読み込む関数を作成します。
セーブする関数は、値が変動する事にセーブされるように、今まで作った関数の中で最後に呼び出すように追記します。
1 2 3 4 5 6 7 8 9 10 11 |
saveItems(){ localStorage.setItem('items', JSON.stringify(this.items)); //this.saveItems() で他の関数から呼び出す } readItems(){ items = localStorage.getItem('items', this.items); if(items){ this.items = JSON.parse(items); } } |
データの呼び出しは、ページが読み込みされた時に実行したいので、テンプレートタグがマウントされた時に実行されるように処理を書きます。
1 2 3 4 5 6 7 8 |
//読み込み時にデータ読み込み&スタイルを変更する this.on("mount", function() { this.readItems(); //データの呼び出し for(var i = 0; i < this.items.length; i++){ //呼び出したデータの一つ一つにスタイルを設定する this.changeHpStyle(i); } }); |
出来上がり
大方出来上がりました!最後に、より便利にするためにバーの中に、透明な「最大値にする」ボタンと「最小値にするボタン」を組み込みました。
完成系はcodePenで公開しますので、ソースコード等自由に見てください。
さいごに
大規模な開発には向かないとのことですが、このくらいのちょこちょこっとしたものであれば簡単に実装できていいなと思いました。
Riot.jsには、jQueryのajaxのような非同期通信の関数はありませんが、こちらも別のライブラリで対応が可能です。
簡単な動的表示や操作だったらかなり使い勝手がいいなと思いました。