LoginSignup
3
0

More than 3 years have passed since last update.

【Vue + ApexCharts】データを集計して円グラフに表示させる

Last updated at Posted at 2020-11-23

はじめに

皆さんおはこんばにちは。
エンジニア歴1年目、現場経験ゼロの弱小自称 Web エンジニアです。

Vue のアプリケーション開発で、見た目がシャレ乙な ApexCharts を導入してみたは良いものの
どうやってデータを詰めたらいいんジャイ!!となったので
本記事を作成するにいたった次第でございます。

やりたいこと

・ApexChartsを使って円グラフを表示させる。
・ストアに格納したデータの集計をその円グラフに反映させる。

image.png

環境

・Vue CLI v3.5.0
・Node v12.18.4
・Npm 6.14.6
・Vuetify 2.3.18
・ApexCharts 1.6.0

コードサンプル

本記事の目的は用意されたデータを如何にして ApexCharts に適用させるかなので
Vueプロジェクトの作成方法やデータの格納方法などは割愛します。

もし、プログラムを実際に動かしてみて確認したい方がいましたら
以下のコードサンプルをご活用ください。

Vuetifyの導入に必要なターミナルコマンド
$ vue add vuetify


App.vue

<template>
  <v-app>
    <v-main>
      <router-view />
    </v-main>
  </v-app>
</template>


Form.vue
<template>
    <v-layout row wrap justify-center>
        <v-flex xs5 mt-5>
            <v-card>
                <v-card-title>
                    <v-flex xs12 class="text-center">
                        支出フォーム
                    </v-flex>
                </v-card-title>

                <v-divider></v-divider>

                <v-card-text>
                    <v-form ref="test_form">
                        <v-text-field v-model="expenditure.price" label="支出額:" :rules="[numberRules.required,numberRules.regex]">
                            <template v-slot:append></template>
                        </v-text-field>

                        <v-radio-group row label="カテゴリー:" v-model="expenditure.category">
                            <v-radio label="食費" value="食費"></v-radio>
                            <v-radio label="交通費" value="交通費"></v-radio>
                            <v-radio label="住居費" value="住居費"></v-radio>
                            <v-radio label="その他" value="その他"></v-radio>
                        </v-radio-group>
                    </v-form>
                </v-card-text>

                <v-divider></v-divider>

                <v-card-actions>
                    <v-flex class="text-center">
                        <v-btn dark depressed @click="submit" color="info">入力</v-btn>
                    </v-flex>
                </v-card-actions>
            </v-card>
        </v-flex>
    </v-layout>
</template>

<script>
import { mapActions } from 'vuex'

export default {
    data() {
        return {
            //フォームに入力された値
            expenditure:{},
            //入力規則
            numberRules: {
                required: value => !!value || "未入力は許さない",
                regex: value => /^[0-90-9]+$/.test(value) || "数字だけ入力してちょ",
            },
        }
    },

    methods: {
        submit() {
            if (this.$refs.test_form.validate()) {
                this.expenditure.price = Number(this.expenditure.price); //入力された支出額を数値に変換
                this.addExpenditure(this.expenditure); //actions の addExpenditure を呼び出し
                this.$router.push({name:'Chart'}); //ルーティング
                this.expenditure = {}; //空に戻す
            }
        },
        ...mapActions(["addExpenditure"]),
    }
}
</script>


Chart.vue
<template>
    <v-layout row wrap justify-center>
        <v-flex xs5 mt-5>
            <v-card>
                <v-card-title>
                    <v-flex xs12 class="text-center">
                        円グラフ
                    </v-flex>
                </v-card-title>

                <v-divider></v-divider>

                <v-card-text>
                    <!-- ここに円グラフを表示させるためのタグを書く -->

                </v-card-text>

                <v-divider></v-divider>

                <v-card-actions>
                    <v-flex class="text-center">
                        <v-btn dark depressed @click="returnPage" color="info">戻る</v-btn>
                    </v-flex>
                </v-card-actions>
            </v-card>
        </v-flex>
    </v-layout>
</template>

<script>
export default {
    methods: {
        returnPage() {
            this.$router.push({name:'Form'}); //ルーティング
        }
    }
}
</script>


router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'

import Form from '../views/Form.vue'
import Chart from '../views/Chart.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Form',
    component: Form
  },
  {
    path: '/chart',
    name: 'Chart',
    component: Chart
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router


store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    expenditures:[], //支出データを保存する配列
  },
  mutations: {
    //支出データを state の expenditures に追加
    addExpenditure(state, expenditure) {
      state.expenditures.push(expenditure)
    }
  },
  actions: {
    //支出データを追加する mutations の呼び出し
    addExpenditure({commit}, expenditure) {
      commit('addExpenditure', expenditure)
    }
  },
  getters: {
  }
})

ApexCharts のインストール

$ npm install vue-apexcharts

円グラフの表示

まずは以下の記事を参考に円グラフを表示させてみます。
円グラフのコードサンプル

Chart.vue
<apexchart type="pie" height="400" :options="chart.options" :series="chart.series"></apexchart>
<script>
import VueApexCharts from 'vue-apexcharts'

export default {
    components: {
        apexchart: VueApexCharts,
    },

    data: () => ({
        chart: {
            options: {
                labels: ['食費','交通費','住居費','その他'],
                title: {
                    text: 'ジャンル別 支出割合',
                    align: 'center',
                },
            },
            series: [4, 2, 5, 3],
        }
    }),

seriesは、データのオブジェクトの配列を受け付けるオプションです。
labelsは、seriesの配列に対応した配列を受け付けるオプション。

今回の場合であれば
食費、交通費、住居費、その他の割合が 4:2:5:3 の円グラフが表示されます。

算出されたデータの表示

本題はここから。

先程は適当な数値を入れて円グラフを表示させましたが
自前で用意したデータの集計を表示させたい。

その場合は、加工したデータを配列に詰めちゃえばいいわけです。
(結局seriesは配列を受け付けるので。)

今回は state 内のデータを加工するので getters 内で算出処理をする。

store/index.js
getters: {
  chartSeries: (state) => {
    let foodSum = 0; //食費支出額の合計
    let transportationSum = 0; //交通費支出額の合計
    let housingSum = 0; //住居費支出額の合計
    let othersSum = 0; //その他の支出額の合計

    for (let ex of state.expenditures) {
      if (ex.category === '食費') {
        foodSum += ex.price;
      } else if (ex.category === '交通費') {
        transportationSum += ex.price;
      } else if (ex.category === '住居費') {
        housingSum += ex.price;
      } else if (ex.category === 'その他') {
        othersSum += ex.price;
      }
    }

    return [foodSum, transportationSum, housingSum, othersSum]; //それぞれの合計が詰まった配列
  }
}

後は、series: [4, 2, 5, 3]を消して以下のように書き換えれば、ほい完成。

Chart.vue
<apexchart type="pie" height="400" :options="chart.options" :series="$store.getters.chartSeries"></apexchart>

参考記事

Vue.jsでApexchartsを使ってグラフ描画を行う

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0