【JavaScript実践】瞑想アプリの作り方を勉強したよ

JavaScriptの使い方を学ぶために以下の動画を使って瞑想アプリの作り方を勉強したよというのと、動画を参考に作成したアプリに少しだけ追加したコードの記録です。

参考動画: Build A Meditation App With Javascript HTML & CSS!
https://www.youtube.com/watch?v=oMBXdZzYqEk

やったこと

動画の説明欄「Materials used in this video:」のURLから使用する素材をダウンロード→動画の説明に従って作成しました。

エディタは動画内で使用していたVisual Studio Codeをインストールして使用しました。

感想

動画は全編英語。ですが講師の話し方が聞き取りやすいので、動画内にある通りてこてこ文字を打ち込んでいけばさくさく進めました。たった45分の動画なのも嬉しい。

SVGを扱うのは初めてだったのでへぇ~便利~と唸りながら楽しく学習しました。

個人的に修正したこと

動画に従ってアプリを作成したあと、気になった部分があったので以下の修正のためコードを追加・修正しました。

  • タイマー表記を「2:0」から「2:00」に修正
  • 分数を設定した際にカウントダウンをリセット
  • 背景動画を常に全体に表示
  • 少しだけレスポンシブ対応

タイマー表記を「2:0」から「2:00」に修正

タイマーの秒数が一桁の場合、「2:0」という表示になってしまっていたので、よく見る「2:00」に修正するために「app.js」の以下の二か所を修正しました。(0を追加したあと、String.prototype.slice()で下2文字を取り出す)

//Select sound
timeSelect.forEach(option => {
    option.addEventListener('click', function() {
        fakeDuration = this.getAttribute("data-time");
    //以下を修正
        timeDisplay.textContent = `${Math.floor(fakeDuration / 60)}:${("0" +
        Math.floor(fakeDuration % 60)).slice(-2)}`;
    });
});
//We can animaited the circle
    song.ontimeupdate = () =>{
        let currentTime = song.currentTime;
        let elapsed = fakeDuration - currentTime;
    //以下1行を修正
        let seconds = ("0" + Math.floor(elapsed % 60)).slice(-2);
        let minutes = Math.floor(elapsed / 60);
        //省略
        }

参考:javascriptで数字を2桁で表示する方法
https://qiita.com/stivan622/items/d6e32475174c94648c6a

分数を設定した際にカウントダウンをリセット

作成したアプリはタイマーの分数を変更しても、変更前のカウントダウンが残っていました。

例えば10分でタイマーを再生し、→9:50でタイマー停止→分数変更(例えば2分を設定)すると画面上の数字は「2:00」と表示されました。しかし、そこからふたたび再生を押すと「1:50」からカウントダウンが始まってしまいます。これを「2:00」からカウントダウンできるよう 「app.js」を修正しました。

//Select sound
timeSelect.forEach(option => {
    option.addEventListener('click', function() {
        fakeDuration = this.getAttribute("data-time");
        timeDisplay.textContent = `${Math.floor(fakeDuration / 60)}:${("0" +
        Math.floor(fakeDuration % 60)).slice(-2)}`;
    //以下を追加
        song.currentTime = 0;
    });
});

背景動画を常に全体に表示

作成したアプリでは背景の動画を「width: 100%」で設定していました。

そのため、ブラウザのサイズを縦長に変更すると動画の下に空白ができてしまっていました。

個人的に見栄えが良くなかったため 「index.html」「style.css」「app.js」をそれぞれ修正しました。

        <div class="vid-container">
           <!--  idを追加 -->
            <video id="mainVideo" loop>
                <source src="./video/rain.mp4" type="video/mp4" />
            </video>
        </div>
/* 以下のwidth指定を削除 */
video{
    position: fixed;
    top: 0%;
    left: 0%;
    z-index: -10;
}
/* ブラウザを開いた時のサイズ指定を追加 */
.mainVideo {
    height: 100vh;
    width: auto;
}
   //以下を追加 
   //landscape or portrait
    window.addEventListener('resize', () =>{
        let viewHeight = window.innerHeight;
        let viewWidth = window.innerWidth;
        let windowSize = viewHeight/viewWidth;
        const mainVideo = document.getElementById("mainVideo").style;
        if (windowSize < 0.55){
            mainVideo.width = "100%";
            mainVideo.height = "auto";
        } else {
            mainVideo.width = "auto";
            mainVideo.height = "100vh"; 
        }
    });
    

具体的には、ブラウザサイズの変更時にブラウザの縦(viewHeight)と横(viewWidth)のサイズとその比率(windowSize)を取得し、その比率が0.55より小さいときは横幅100%、それ0.55以上の場合は縦幅100vhにHTMLを書き換えています。

別の方法も試したのですが、

・縦幅100vhで指定→その状態でブラウザを小さくすると動画の上部だけが表示され、雨が水たまりに落ちる部分が見えなくなってしまった。

・背景画像のCSS指定(background-size: cover;)の要領でできないかと思った→背景画像には動画を指定できない。

・mediaのorientationでブラウザの状態(縦長・横長)を判別して振り分けようとした→ブラウザサイズによって微妙に空白ができてしまう

という紆余曲折を経てJavaScriptで調整しました。が、ただ先程見つけた下のページが正解だったかも……次の機会に下の方法で試してみます……。

画面全体に背景動画を流す
https://coco-factory.jp/ugokuweb/move01/6-3-1/

少しだけレスポンシブ対応

ブラウザサイズを変更した際にボタンの表示が重なってしまっていたので、ブラウザ幅が570px以下の場合はFlexBoxを縦並びにして表示が重ならないように修正しました。

@media screen and (max-width: 570px) {
   .app {
       flex-direction: column;
   }
   .time-select,
   .sound-picker,
   .player-container{
       width: 80%;
   }
   .time-display{
       bottom: 0;
   }
}

あまり見栄えは良くないけれど一応最低限のレスポンシブ対応です。

おわり。