学びたてだけどVue.js + CSSアニメーション + 絵を組み合わせて作ってみたい!
という事でシンプルなカップラーメンのタイマーを作ってみました。
基本的なVue.jsで始めたばかりの方でも比較的読み進めやすいと思います。
話題のFirebaseで無料公開もとても簡単だったので方法をまとめました。
🍜 ラーメンタイマー
 
・アプリURL
https://ramen-timer.com/
・GitHub - ソースコード
https://github.com/aocattleya/Ramen-Timer
(いいねやスター貰えるととても喜びます!)
 
アプリの内容
| 使用している物 | 説明 | 
|---|---|
| HTML, CSS | animationプロパティを使用 | 
| Vue.js | JavaScriptフレームワーク | 
| Firebase | 無料枠でアプリを公開する | 
| --- | --- | 
| SweetAlert | アラートを簡単にデザインするライブラリ | 
| GoogleFonts | フォントの変更 | 
| FireAlpaca | ペイントツール(無料) | 
 
3分 or 5分のボタンをホバーするとキャラクターが左右に振り向きます。
時間を選びクリックするとカウントダウンタイマーが使える簡単な内容です。
レスポンシブデザイン(スマホ)にも対応しています。※左右の振り向きはしない

キャラクターデザイン
まず一番目立つキャラクター
自分は元々漫画家のアシスタントをしていた時期などがあり、
描いた物をアプリに組み合わせてみたかったので描き描き。

レイヤーといって何枚もの板が重なっているように描かれています。
なので例えば手を消すと下に隠れている髪が出てきます。
これによって一枚描いたら背景などが簡単に変更でき、左右反転させて手を描けば2枚完成。
※猫の方が万人受けする。名前募集中!
こちらに原寸サイズ画像&レイヤーファイルを公開しています。
illustration-Original_Characters(GitHub)
 
🔍 コードの解説
それぞれ分けて解説していきます。
コードは分かりやすいように関係ない部分を大幅に省略して書いてます。
・キャラクターを左右に振り向かせる
1行目、v-bind:class=""によってclassを「右顔CSS」⇔「左顔CSS」と書き替えており、
きっかけは、それぞれの3分と5分ボタンにあるv-on:mouseover=""
<!-- キャラクター -->
<img v-bind:class="{ right_face: isRight, left_face: isLeft }" />
  <div class="pick-button">
    <!-- 3分ボタン -->
    <input type="image" src="img/3min.png" v-on:mouseover="rotate_left" />
    <!-- 5分ボタン -->
    <input type="image" src="img/5min.png" v-on:mouseover="rotate_right" />
  </div>
</div>
 
JavaScript側では下記のようにボタンをホバーした時に、
「true」⇔「false」で切り替わる処理を書いています。
const vm = new Vue({
  el: "#app",
  data: {
    isLeft: false,
    isRight: true,
  },
  methods: {
    rotate_left: function() {
      this.isLeft = true;
      this.isRight = false;
    },
    rotate_right: function() {
      this.isLeft = false;
      this.isRight = true;
    }
  }
});
 
右顔のCSSアニメーション
.right_face {
  border-radius: 50%;
  background-image: url(../img/button_right.png);
  animation: anime 0.4s linear 2;
}
@keyframes anime {
  100% {
    transform: rotateY(360deg);
  }
}
・border-radius: 50%で画像を丸くする。
・そしてanimationプロパティ、長さなどを設定でき@keyframesで動きを付けます。
 上記は100%終了時までにY軸に360度回転としています。
 
 
 
・ボタン選択で画面の切り替え
ページは変わっていません。
Vue.jsで最初の画面を非表示にし、非表示になっていたタイマー画面を表示させています。

3分 or 5分ボタンを押すとv-on:click="show = !show"によって、
<div v-show="!show"> ⇔ <div v-show="show">と画面表示が切り替わります。
<!-- 3分 or 5分ボタン選択画面 -->
<div v-show="!show">
  <input type="image" src="img/3min.png" v-on:click="show = !show" />
  <input type="image" src="img/5min.png" v-on:click="show = !show" />
</div>
<!-- タイマー画面 -->
<div v-show="show">
  <span id="minutes">{{ minutes }}</span>
  <span id="middle">:</span>
  <span id="seconds">{{ seconds }}</span>
  <!-- 省略 -->
</div>
 
 
・タイマーの実装
<!-- 3分 or 5分ボタン -->
<input type="image" src="img/3min.png" v-on:click="show = !show; threeMin()" />
<input type="image" src="img/5min.png" v-on:click="show = !show; fiveMin()" />
3分 or 5分ボタンをクリックした時に、
v-on:click="threeMin()"又はv-on:click="fiveMin()"が実行され、
タイマー画面でカウントする時間を3:00 or 5:00にします。
 
<!-- タイマー -->
<div class="timer">
  <span id="minutes">{{ minutes }}</span>
  <span id="middle">:</span>
  <span id="seconds">{{ seconds }}</span>
</div>
<div id="buttons">
  <!-- スタート -->
  <input type="image" src="img/start.png" v-on:click="startTimer" v-if="!timer" />
  <!-- ストップ -->
  <input type="image" src="img/stop.png" v-on:click="stopTimer" v-if="timer" />
  <!-- リセット -->
  <input type="image" src="img/reset.png" v-on:click="resetTimer" v-if="resetButton" />
</div>
タイマーのカウントは、HTMLの{{ minutes }} : {{ seconds }}
この部分がVue.jsの処理でタイマーのように変更されていきます。
 
const vm = new Vue({
  el: "#app",
  data: {
    timer: null,
    pickTime: null,
    totalTime: null,
    resetButton: false
  },
  methods: {
    // 3分 or 5分ボタン
    threeMin: function() {
      this.pickTime = 3 * 60;
      this.totalTime = this.pickTime;
    },
    fiveMin: function() {
      this.pickTime = 5 * 60;
      this.totalTime = this.pickTime;
    },
    // スタート
    startTimer: function() {
      this.timer = setInterval(() => this.countdown(), 1000);
      this.resetButton = true;
    },
    // ストップ
    stopTimer: function() {
      clearInterval(this.timer);
      this.timer = null;
      this.resetButton = true;
    },
    // リセット
    resetTimer: function() {
      this.totalTime = this.pickTime;
      clearInterval(this.timer);
      this.timer = null;
      this.resetButton = false;
    },
    // 秒が一桁の場合0を追加
    padTime: function(time) {
      return (time < 10 ? "0" : "") + time;
    },
    // カウントダウン
    countdown: function() {
      if (this.totalTime >= 1) {
        this.totalTime--;
      } else {
        this.totalTime = 0;
        this.resetTimer();
        swal("Complete!!", "", "success");
      }
    }
  },
  computed: {
    // タイマーの数値
    minutes: function() {
      const minutes = Math.floor(this.totalTime / 60);
      return minutes;
    },
    seconds: function() {
      const seconds = this.totalTime - this.minutes * 60;
      return this.padTime(seconds);
    }
  }
});
computed:の部分がHTMLのタイマー{{  }}に表示され、ボタンで各methods:が働き、
スタートを押すとsetInterval()により、一秒ごとにcountdownが実行されます。
 
 
 
・アラートデザイン『SweetAlert』
簡単にアラートがデザイン出来るライブラリ
ブラウザからCDN経由で読み込みができます。
<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
swal("Complete!!", "", "success");
これだけ、凄い!
このアラートはスマホでも同じデザインで表示されます。
その他の使い方は下記のページが分かりやすいです。
🌐 Firebaseで公開(無料)
Firebase - Google
 
最近とても話題のFirebaseで、作成したアプリを無料で公開。
データベースなど複雑に使う事も可能ですが、今回は簡単に無料で公開してみます。
下記はQiita用にtestプロジェクトで進めていますが、任意の名前にしてください。
1、ログイン
Firebaseのページを開いてログイン
2、プロジェクトの作成

プロジェクト名を記入します。
IDの部分はURLになりますので好みのIDに書き変えましょう。
Googleアナリティクスの設定を聞かれます。
今回は、使用しないで進めます。
3、フォルダの設定

Desktopにプロジェクト名と同じフォルダを作成します。
中にpublicという名前でフォルダを作成して公開したいコードを入れます。

4、Node.jsのインストール
まだ入ってない方はインストールしてください。
すぐ終わります。
5、firebase-toolsをインストール
npm install -g firebase-tools
6、ログイン
firebase login
利用状況のデータを送っても良いか聞かれたら任意でY/n
次にGoogleログイン画面が表示されるので、アカウントを選び進めます。
7、デプロイ設定
cd Desktop/test
プロジェクトのフォルダに移動します。
firebase init
◉ Hosting: Configure and deploy Firebase Hosting sites
Hostingをスペースで選択してからEnterを押します。
※スペースで選択していなとエラーとなる。
? Please select an option: 
Don't set up a default project を選択してEnter
? What do you want to use as your public directory?(public)
そのままEnter(デフォルトのpublicとなる)
? Configure as a single-page app (rewrite all urls to /index.html)? (y/N) 
そのままEnter(デフォルトでN)
? File public/index.html already exists. Overwrite? (y/N) 
index.htmlを上書きしていいか聞いてくるのでN(そのままEnterでN)
 上手くいきました。
上手くいきました。
8、公開する
firebase use --add
上記でEnter
? Which project do you want to add?
> test-71a0e
作成したプロジェクトを選択します。
? What alias do you want to use for this project? (e.g. staging)
名前は任意です。今回はstagingとしました。
firebase deploy
完了です!

内容を変更した場合は、再度firebase deployすればOKです。
こうして完成、簡単にFirebaseでの公開も出来ました。使ってね!
・ラーメンタイマー
https://ramen-timer.com/
・ソースコード - GitHub
https://github.com/aocattleya/Ramen-Timer
 
 
終わりに
Vue.jsで何か作ってみたい、CSSアニメーションと絵も組み合わせたい!
そんな考えから作ってみたアプリでシンプルに見えて苦戦もありました。
しかし言語を学習してるだけと違い、新たな発見と理解はとても多かったです。
基本的な構文でここまで作れて達成感も大きかったのでやって凄く良かったと思います。
次はさらにレベルを上げて作ってみたいですね!
最後まで読んでくれてありがとうございました。
 
追記(PWA対応)
PWA(Progressive Web Apps)に対応しました。
スマホでアクセスしてホーム画面に追加するとオフラインで使えるタイマーアプリになります。
Macでもオフラインアプリとしてダウンロード出来ます。

参考
・【CSS3】@keyframes と animation 関連のまとめ
・SweetAlertバージョン2を使ったデモ
・Firebaseを用いて5分でセキュアなWebサイトを公開する
リンク
 GitHub
 GitHub
https://github.com/aocattleya
🐦 Twitter
https://twitter.com/aocattleya
📗 Qiita
https://qiita.com/aocattleya




