# Music Player 實作
###### tags: `實作` `CSS` `javascript`
[實作頁面連結](https://allenw0815.github.io/mission/mission_26/index.html)

### Flowchart
1. 寫 HTML 結構
2. 寫 CSS,這實作比較複雜,應會用到偽元素以及 animate
3. 透過 JS 去讓 audio 播放以及暫停
4. 播放以及暫停時分別需要做哪些事情?
5. 讓進度條樣式對應到撥放的時間點上
> JS 流程
1.先把所需的 DOM 取好,用陣列存放歌曲名稱,畫面載入時依照陣列索引的名稱設定是哪首歌
```javascript=
const songs = ['Lost_in_paradise','Desperado','Wild_side','山雀','Yuve_Yuve_Yu']
let songIndex = 1
function loadingSong (song) {
musicName.innerText = song.replaceAll('_',' ') //顯示歌名 替換掉不要的符號
audio.src = `music/${song}.mp3` //找對應音源
img.src = `img/${song}.png` //找對應圖片
}
loadingSong(songs[songIndex])
```
2.點擊播放鍵時,判斷是否正在撥放分別去做暫停及播放兩個相反的 function
```javascript=
const playingMode = () =>{
audio.play() // 音源播放
musicContainer.classList.add('play') // 替元素添加 class 來觸發 animate
playBtn.querySelector('i').classList.remove('fa-play') // 移除當前圖示
playBtn.querySelector('i').classList.add('fa-pause') // 更新圖示
}
function musicPlay() {
const isPlaying = musicContainer.classList.contains('play') // 回傳 Boolean
isPlaying ? pauseMode() : playingMode()
}
playBtn.addEventListener('click',musicPlay)
```
3.前後鍵點擊
```javascript=
function musicNext() {
songIndex < songs.length -1 ? songIndex++ : songIndex // 限制在最後一首
loadingSong(songs[songIndex]) // 更新歌曲
playingMode() // 播放
}
nextBtn.addEventListener('click',musicNext)
```
4.監聽歌曲長度以及當前歌曲時間搭配 CSS 實現進度條動畫及點擊跳轉
```javascript=
function updateProgress(e) {
// 這邊為解構賦值
const {duration,currentTime} = e.srcElement // 取得總長跟播放到的長度
const progressPercent = (currentTime / duration) * 100 // 取得百分比的數字
progress.style.width = `${progressPercent}%` // 讓有顏色的進度條根據進度顯示
}
audio.addEventListener('timeupdate',updateProgress) // 音源播放時持續觸發
// 正確說法是 currentTime 變更時觸發,感覺很耗能應該可以壓低頻率
function setProgress(e) {
const width = this.clientWidth // div的長度
const x = e.offsetX // 點擊位置的長度
const duration = audio.duration
audio.currentTime = ( x / width ) * duration
// 代表點的位置是總長的幾分之幾再*總長就會得出相對應的當前播放時間然後更新currentTime
}
progressArea.addEventListener('click',setProgress)
```
5.歌曲結束後換下一首,就好比結束後觸發點擊下一首按鍵一樣
```javascript=
audio.addEventListener('ended',musicNext)
```
### 紀錄
* currentTime 播放時不停變更

* 動畫可以使用多個效果
```css=
@keyframes rotate {
0%{
transform: rotate(0deg) scale(1);
}
50%{
transform: rotate(180deg) scale(1.1);
}
100%{
transform: rotate(360deg) scale(1);
}
}
```
* 透過兩個重疊但顏色不同的元素,配合 JS 來實現進度條效果
```css=
.music-container .music-info .progress-area{
width:80%;
height: 5px;
border-radius: 10px;
margin-bottom: 15px;
background-color: rgb(235, 233, 233);
cursor: pointer;
}
.music-container .music-info .progress-area .progress{
background-color: rgb(145, 206, 245);
height: 100%;
border-radius: 10px;
width: 0%;
transition: 0.1s linear;
}
```
* 透過添加 class 觸發 aninate 以及 進出場動畫
```css=
.img-container img{
animation-play-state: paused;
}
/* 在最外層元素加上 play 讓動畫開始 */
.music-container.play .img-container img{
animation-play-state: running;
}
.music-info{
opacity:0;
transition: .3s;
}
.music-container.play .music-info{
opacity: 1;
transform:translateY(100%);
}
```
* <font style="color:red">解構賦值</font>抓到對應的key
```javascript=
let {a,b,e} = {a: 10, b: 20, c: 30, d: 40, e:65}
a; // 10
b; // 10
c; // c is not defined
d; // d is not defined
e; // 10
```
[ES6 解構賦值](https://wcc723.github.io/javascript/2017/12/25/javascript-destructuring/)
### 小記
可以作一些補充
* 頁面上添加所有的歌單,直接點擊切換歌曲
* 加上音量功能
* 添加每首歌的秒數以及倒數
* 將旋轉的圖片改為前後各一張的 carousel 也可以透過這邊切歌曲
### 參考
[HTML\<audio><vedio>Property](https://www.w3school.com.cn/tags/html_ref_audio_video_dom.asp)
[timeupdate 事件](https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLMediaElement/timeupdate_event)