SpotifyAPI ＋ Vue.jsで自分が普段よく聴く曲の特徴を可視化する

#概要
まず本記事は、Sportifyの会員でないと実装できないのでご了承ください。
会員でなくてもSportify APIを使ってみたい方は別途記事を投稿しますので、その際はご覧頂けますと幸いです。

今回はSporifyで自分がよく聴く曲を一覧表示し、
それぞれの曲の特徴（詳細については後述）を可視化しする機能を実装します。
また特徴ごとにソートできる機能も作ります。
因みにUIは今回の本題とは関係ないのでテキトーです笑

Sporify APIでは曲ごとに多くの特徴をデータとして持っています。
下記の記事で分かりやすく整理されています。

https://qiita.com/EkatoPgm/items/f88b6f002fd15defce71

その中から曲名と再生時間に加えて下記の特徴を抽出したいと思います。

* アコースティック感(0~1)
* 踊りやすさ(0~1)
* エネルギー感(0~1)
* ライブ感(0~1)
* テンポ感(BPM)

それぞれ数値が高ければ高いほど、特徴が濃いということになります。
※テンポ感(BPM)は高いほど早い

例えばこんな感じで表示されます。

![スクリーンショット 2021-10-30 23.02.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566407/85c6284a-5305-da76-9cda-24d3dc3d1726.png)


#環境
* node.js v10.16.3
* npm 8.1.1
* Vue CLI 4.5.13
* vue 3.3.20


#実装


##事前準備

###axiosとvue routerのインストール
```
$ npm install --save axios vue-axios
$ npm install vue-router
```

###Sportify APIのClient ID取得する

1)まずはSpotify for Developersにログイン

https://developer.spotify.com/dashboard/

2)Spotify Web APIをコールするクライアントアプリケーションをダッシュボードページから登録する。

3)発行されたClient IDを控える

4)「EDIT SETTING」からRedirect URIsに
http://localhost:8080
を設定

下記の記事が参考になります。

https://dev.classmethod.jp/articles/about-using-of-spotify-api/
##ソース

```/main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router/'

const app = createApp(App)
app.use(router)
app.mount('#app')

```

```App..js
<template>
    <div id="app">
        <router-view />
    </div>
</template>

```

```router/index.js
import { createWebHistory, createRouter } from 'vue-router'
import Sportify from '../components/Sportify.vue'

const routes = [
  {
    path: '/',
    name: 'Sportify',
    component: Sportify,
    props: (route) => {
      return { routeParams: route.query }
    }
  }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router

```

```components/Sportify.vue
<template>
    <div class="myTracks" style="text-align:center;">
        <h1>最近よく聴く曲の情報</h1>
        <div v-if="!auth">
            <button @click="spotifyLogin">認証</button>
        </div>
        <div v-else>
            <select v-model="selected">
                <option value="time">再生時間</option>
                <option value="acousticness">アコースティック感</option>
                <option value="danceability">踊りやすさ</option>
                <option value="energy">エネルギー感</option>
                <option value="energy">ライブ感</option>
                <option value="tempo">テンポ感</option>
            </select>
            <div v-if="myTracks != null">
                <ul style="list-style: none;">
                    <li v-for="(val, k) in myTracks" :key="k">
                        <img :src="val.url"/>
                        <div>曲名:{{val.name}}</div>
                        <div>再生時間:{{val.time}}秒</div>
                            <div>アコースティック感:{{val.acousticness}}</div>
                            <div>踊りやすさ:{{val.danceability}}</div>
                            <div>エネルギー感:{{val.energy}}</div>
                            <div>ライブ感:{{val.liveness}}</div>
                            <div>テンポ感(BPM平均):{{val.tempo}}</div>
                    </li>
               </ul>
            </div>
        </div>
    </div>
</template>
<script>
import axios from 'axios'

export default {
    data: function() {
        return {
          auth: 0,
          init: 0,
          tracks: null,
          myTracks: null,
          selected: '',
        }
    },
    props: {
        routeParams: Object
    },

    created() {
        if (this.$route.hash) {
            this.$router.push(this.$route.fullPath.replace('#', '?'))
            this.auth = 1
        }
    },
    updated() {
        // 認証後、初回のみ実行
        if(this.auth && !this.init){
            this.init = 1
            this.getmyTracks()
        }
    },
    methods: {
        spotifyLogin() {
            const endpoint = 'https://accounts.spotify.com/authorize'
            const response_type = 'token'
            // Client ID
            const client_id = '*****************'
            const redirect_uri = 'http://localhost:8080'
            const scope = 'user-top-read'
            location.href = endpoint + '?response_type=' + response_type + '&client_id=' + client_id + '&redirect_uri=' + redirect_uri + '&scope=' + scope
        },
        async getmyTracks() {
            const endpoint = 'https://api.spotify.com/v1/me/top/tracks'
            const data = {
                headers: {
                  'Authorization': this.routeParams.token_type + ' ' + this.routeParams.access_token
                },
            }
            // 自分がよく聴く曲を取得する
            const tracks = []
            await axios.get(endpoint, data).then(res => {
                this.tracks = res.data.items
            })
            .catch(err => {
                console.error(err)
            })

            // 取得した曲のデータを一つ一つ取得する
            for (let i = 0; i < this.tracks.length; i++) {
                await axios.get('https://api.spotify.com/v1/audio-features/' + this.tracks[i].id, data).then(res2 => {
                    tracks.push({
                        url: this.tracks[i].album.images[1].url,
                        name: this.tracks[i].name,
                        time: this.tracks[i].duration_ms,
                        acousticness: res2.data.acousticness,
                        danceability: res2.data.danceability,
                        energy: res2.data.energy,
                        liveness: res2.data.liveness,
                        tempo: res2.data.tempo,
                    })
                })
            }
            this.myTracks = tracks
          },
      },
      watch: {
          // ソート条件が変わったらソート実行
          selected() {
              this.myTracks.sort((a, b) => {
                  return (a[this.selected] < b[this.selected]) ? 1 : -1;
              })
          },
      }
}
</script>

```
##やってること
1)認証ボタンを押すと
https://accounts.spotify.com/authorize
にClient IDなどのパラメーターをつけてログインする。

2)認証されるとリダイレクトURIに設定したlocalhost:8080に遷移し、アクセストークンを得ることができる。（URIに含まれている）
https://api.spotify.com/v1/me/top/tracks
に取得したアクセストークン等のパラメーターをつけて、自分がよく聴く曲20曲（デフォルト）を取得する。

3)曲の情報をループしそれぞれの特徴を取得する。

4)一覧表示する
またプルダウンで再生時間、アコースティック感、踊りやすさ、エネルギー感、ライブ感、テンポ感を降順でソートできる。

#最後に
Spotifyすご...
色んなデータ持ちすぎててもはや怖いです。