Nuxt.jsとChart.jsとRakuten RapidAPIで新型コロナウィルス感染症のデータを表示させてみる


作ったもの

世界の新型コロナウィルス感染症のデータを表示させてるだけのページになります。

STAY HOMEのゴールデンウィークでちょっといじってみようと思って、やってみました。
東京都の有名になったあのサイトもNuxt.js を使ってますが、あれほどのものじゃないです。
あと、APIは英語なので、国名は英語になります。

ひとまずGithub pagesで静的ページが見れます。
https://seki0809.github.io/covid19/

ソースコードはこちら
https://github.com/seki0809/covid19

↓ファーストビューに世界の合計が表示されます。

国ごとの一覧が表示されます。
国の一覧で「累計感染者」「現在感染者」「回復者」「死亡者」の見出し押すと並び替えをします。(降順のみ)

↓国の一覧から国を選択すると、その国の日毎のグラフが見れます。

使ったもの

  • Nuxt.js
  • Rakuten RapidAPI
  • Chart.js
  • axios
  • PHP

Nuxt.js で何か作りたかったのと、Rakuten RapidAPI で何か作りかったというのがあります。

ただ、フロントエンドはNuxt.jsですが、RapidAPIからの取得と加工はPHPでやってます。

Nuxt.js

Nuxt.jsのインストールについて書いた記事はこちら。

nuxt.jsインストール手順備忘録
https://qiita.com/seki0809/items/5f831d63146e44dc106a

Rakuten RapidAPI

データはRakuten RapidAPI から取得しています。

最初は下記が完全無料で良いと思って作っていたのですが、3月20日以降しかデータが入っていなかったので、断念しました。
https://api.rakuten.net/api-sports/api/covid-193

で、こっちは登録が必要でしたが、1月22からのデータがあったので、こちらを使いました。
https://api.rakuten.net/Gramzivi/api/covid-19-data

やったこと

バックエンド側

バックエンド側はPHPで書いてます。

1.Jsonの保存

アクセスがあるたび毎回APIを叩くわけにはいかないので、一旦Jsonをファイルとして保存しました。
これはPHPで処理します。

2.Jsonの加工

保存したJsonのデータは日ごとにファイルが別れていたので、1つにまとめます。
ここまでバックエンド側はPHPで書いてます。

フロントエンド側

ここからフロントエンド側のNuxt.jsになります。

3.世界の合計を表示

↓これは単純にJsonから表示させているだけです。

getSummary() {
  const action = `${this.apiUrl}json/summary/summary.json`
  axios.get(action)
    .then(response => {
      this.summary = response.data[0]
    }).catch(error => {
    console.error(error)
  })
}

3.世界の一覧を表示

国の一覧はJsonを取得して、デフォルトは累計感染者の降順にして、表示後は見出しをクリックした箇所で降順に並び替えます。

↓最初の取得です。

getCountries() {
  const action = `${this.apiUrl}api/get_country_list`
  axios.get(action)
    .then(response => {
      this.countries = response.data
      this.sortCountries()
    }).catch(error => {
    console.error(error)
  })
},

↓並び替えの着火です。targetが並び替えする対象です。

changeSort (target) {
  this.sort = target
  this.sortCountries()
},

↓並び替えの本体です。
あとでリファクタリングはした方が良さそうです。

sortCountries() {
  const compare = (a, b) => {
    if(a.target > b.target) return -1;
    if(a.target < b.target) return 1;
    return b - a
  }
  let temp = []
  this.countries.forEach((row, index) => {
    temp.push(
      {
        key: index,
        target: row.total[this.sort]
      }
    )
  }, this)
  temp.sort(compare)
  let array = []
  temp.forEach((row2) => {
    this.countries.forEach((row3, index3) => {
      if (row2.key === index3) {
        array.push(row3)
      }
    }, this)
  })
  this.countries = array
}

4.詳細ページでグラフを表示

↓まずはJsonを取得します。

getHistory() {
  const action = `${this.apiUrl}api/get_country_history/${this.params}`
  axios.get(action)
    .then(response => {
      this.history = response.data
      this.createChart();
    }).catch(error => {
    console.error(error)
  })
}

↓Chart.jsは1つずつ配列が必要なので、必要な部分を抽出して分けます。

createChart () {
  this.history.forEach((row, index) => {
    this.chartDate[index] = row.date
    this.chartConfirmed[index] = row.total.confirmed
    this.chartRecovered[index] = row.total.recovered
    this.chartDeaths[index] = row.total.deaths
    this.chartActive[index] = row.total.active
  }, this)
  this.outputChart()
}

↓Chart.jsでグラフを表示させます。

outputChart () {
  const ctx = document.getElementById('chart').getContext('2d')
  new Chart(ctx, {
    type: 'bar',
    data: {
      datasets: [
        {
          label: '死亡者',
          data: this.chartDeaths,
          type: 'line',
          order: 1,
          borderColor: '#0d70ff',
          backgroundColor: '#9ec6ff'
        },
        {
          label: '回復者',
          data: this.chartRecovered,
          type: 'line',
          order: 2,
          borderColor: '#23d5ae',
          backgroundColor: '#a7eedf'
        },
        {
          label: '現在感染者',
          data: this.chartActive,
          type: 'line',
          order: 3,
          borderColor: '#fc0368',
          backgroundColor: '#fe9ac3'
        },
        {
          label: '累計感染者',
          data: this.chartConfirmed,
          order: 4,
          borderColor: '#fedaa0',
          backgroundColor: '#fedaa0'
        }
      ],
      labels: this.chartDate
    },
    options: {
      responsive: false
    }
  })
}

所感

こんな感じです。

最初は機能ごとにコンポーネントを分けていましたが、とくに再利用性は無いので、pagesの中に入れてしましました。

バックエンド側でPHPでも結構書いてるのですが、今回は省略です。

デザインはグリッドのフレームワークだけ引用し、あとは勘で書いてます。
(スマホは見にくいです)

一周回って中国の方が安全って言われてますけど、
下の画像で、上のグラフが中国で下が日本なんですが、やはり中国のピークは2月下旬までで、日本は3月の後半から上がり続けてるんですよね。

1日でも早く日常が戻ってくることを願ってます。

追記

どうやらAPIが有料になったらしく、データの更新は止めます