【リハビリJS学習】瞑想アプリを作る⑤

JS学習のため、瞑想アプリ作成をする第五回。

↓前回はこちら

https://qiita.com/sakuc47/items/3b346efee45aed785da6

### 16. プログレスバーのアニメーション化を解説
```js
    // プログレスバーをアニメーション化する
    let progress = outlineLength - (currentTime / fakeDuration) * outlineLength;
    outline.style.strokeDashoffset = progress;    
```

上記部分が理解できていなかったので読み解いていく。

#### 変数の確認
- `currentTime`：現在の曲の再生位置（秒単位）を表す変数
- `fakeDuration`：別の場所で定義されている、曲の継続時間を表す変数
```js
    // 継続時間（実際には曲全体の長さを取得するのではないので fake とする
    let fakeDuration = 600;`
```

- `outlineLength`： プログレスバーの全体の長さを表す変数

#### `(currentTime / fakeDuration) * outlineLength`
式 (currentTime / fakeDuration) は
現在の再生位置を全体の再生時間で割った値。曲の現在の進行度（0から1の範囲）が計算される。

#### `(currentTime / fakeDuration) * outlineLength`
現在の進行度にプログレスバーの全体の長さを掛けることで、現在のプログレスバーの位置をピクセル単位で表している。

#### `outlineLength - (currentTime / fakeDuration) * outlineLength`
プログレスバーの全体の長さから現在のプログレスバーの位置を引くことで、残りのプログレスバーの位置を計算している。

#### `outline.style.strokeDashoffset = progress;`
outline は別の場所で定義されている、プログレスバー要素を指す変数。（上の方）
```js
  const outline = document.querySelector('.moving-outline circle');
```
SVGのパスの strokeDashoffset プロパティ。（第3回でやった）
パスの描画を開始する位置を制御する。

https://qiita.com/sakuc47/items/c4f1b36715e4a11f6ffc


`strokeDashoffset`の値を`progress`に設定することで、残りのプログレスバーの位置が更新されアニメーション化されていく。（イメージはできるんだけど言語化がむずかしい・・・）

```js
 // プログレスバーをアニメーション化する
 // pregress = 残りの残りのプログレスバーの位置
    let progress = outlineLength - (currentTime / fakeDuration) * outlineLength;
 // プログレスバーのパスの描写の制御 = progress
    outline.style.strokeDashoffset = progress; 
```
`ontimeupdate` イベントが発生するたびに、曲の再生位置に応じたプログレスバーの位置が計算され、表示されるようになる。

### 17. 時間を表示できるようにする
バッククォートと`{}`を使っているので注意。
```js
    timeDisplay.textContent = `${minutes}:${seconds}`;
```

時間も動くようになった！
![スクリーンショット 2024-06-27 0.01.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524465/0ee0a119-49ed-ff89-23e9-7582e0d42a3e.png)

### 18. 時間を選択できるようにし、時間表示を変化させる
時間表示の下に`timeSelect`変数を追加。
```js
  // 時間表示
  const timeDisplay = document.querySelector('.time-display');
  // 時間選択ボタン
  const timeSelect = document.querySelectorAll('.time-select button');
```

``` js
  // 音楽の長さを選択できるようにする
  timeSelect.forEach(option => {
    option.addEventListener('click', function(){
      fakeDuration = this.getAttribute('data-time');
      // 表示されている時間を更新
      timeDisplay.textContent = `${Math.floor(fakeDuration / 60)} : ${Math.floor(
        fakeDuration % 60
      )}}`
    })
  })
```

時間選択ボタンを押すと、時間表示が連動して変わるようになった！
![スクリーンショット 2024-06-27 0.25.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524465/9cafdaec-a7f5-b104-4f5d-90b2cec38886.png)

htmlのdata-timeを修正してみる

```html
      <div class="time-select">
      // 120から10に
        <button data-time="10">2 Minutes</button>
        <button data-time="300">5 Minutes</button>
        <button data-time="600">10 Minutes</button>
      </div>
```
2 Minutesを押すと、時間表示が10秒になるように変化した。
![スクリーンショット 2024-06-27 0.28.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524465/38321d1d-4476-5fbb-1672-b918a67b7a42.png)


再生ボタンを押して10秒経つと、、、マイナスになる。
いつ終わるかが制御できていない。
（でも時間に合わせてプログレスバーが変化するのはうまくできていそう。）

![スクリーンショット 2024-06-27 0.29.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524465/bcd7270a-8f94-df2b-e4ff-eed4b1517e46.png)

`song.ontimeupdate = () => ~~~~`の後半に記述を追加する。

```js
    if(currentTime >= fakeDuration) {
      song.pause();
      song.currentTime = 0;
      play.src = './svg/play.svg';
      video.pause();
    }
```

もう一度再生してみると、カウントが0になると音楽・動画が一時停止され、再生ボタンの画像が元にもどる。


### 19. 音楽を選択できるようにする
```js
  // 音楽を選択できるようにする
  sounds.forEach(sounds => {
    sounds.addEventListener('click', function(){
      song,src = this.getAttribute('data-sound');
      video.src = this.getAttribute('data-video');
      checkPlaying(song);
    })
  })

  // 音楽を再生
  play.addEventListener('click', () => {
  //~略~//
```

![スクリーンショット 2024-06-27 0.49.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524465/56564698-c50f-b6e5-fdf0-8cc6f3cd1b0c.png)

### 20. プログレスバーのアニメーション開始地点を修正し、頂点から始まるようにする

SCSSの`.player-container　svg`を-90度回転させる。
```scss
.player-container {
  position: relative;
  svg {
     // ~　略~ // 
    transform: translate(-50%, -50%) rotate(-90deg);
    pointer-events: none; // SVGが邪魔して再生ボタンを押せないため
  }
}
```

表示確認で問題なければ、indec.htmlの、2Minutesのdata-timeを120に戻す。
```html
    <button data-time="120">2 Minutes</button>
```

完成した！！
![スクリーンショット 2024-06-27 0.57.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524465/d9508b0b-6263-184a-2ead-804c943af4d4.png)


仕事ではスゴイ人たちが制作した難しいスクリプトばかりで読み解きまでに時間がかかるし、何かをゼロから作成することもむずかしかったのだが、ひとつひとつ順を追って作成していけば良いのだという基本的な考え方に立ち返れてよかった。


時間表示を00:00にするなど細々と微調整をしたい部分はあるので、時間ができたらやりたい！

また別の課題にも挑戦しようと思う。
次回はもう少し自分で考えながら作れたら良いな。あせらず少しずつ🐣

https://www.youtube.com/watch?v=oMBXdZzYqEk

https://qiita.com/baby-degu/items/33acb94e404feaf58d35#1%E7%9E%91%E6%83%B3%E3%82%A2%E3%83%97%E3%83%AA%E3%82%92%E4%BD%9C%E3%82%8B