19
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Laravel上でVue.jsとChart.jsを利用してグラフを描いてみる

Last updated at Posted at 2018-05-08

はじめに

もう一度、自分なりに最初っからvueの環境を構築する手順をまとめてみようと思いました。
ついでにchart.jsの導入と動くサンプルを乗っけてます。
素のchart.jsを触ったことはありましたが、コンポーネント化することでいろいろと使い勝手が上がりそうな予感。
Laravelプロジェクトとして作成したけど、ぶっちゃけLaravel要素ほぼないですよね...まあ今後なにか使うときのベースになればなって感じです。

動くやつ

面倒が嫌いな人のために先に GitHub を乗っけておきます。
今回はプロジェクト内にHomesteadをインストールしているため、簡単にう、動きますよ。

動かすまでの手順

先にHomesteadとかcomposerとか、node.jsとかの環境は整っていることとします。

console
git clone https://github.com/tosite0345/vue-chartjs-sample.git

# PHP側パッケージファイルのインストール
composer install

# VM作成
vendor/bin/homestead make

# js側パッケージファイルのインストール
npm install
# 場合によってはこっち
# npm install --no-bin-links
# それでもうまくいかない場合は「導入までの完全な手順」からキャッシュ消去を試す

vagrant up

ちなみにnpm installをローカルマシン側でやってるのは主に処理速度的観点からです。

vagrant起動時にエラーが発生した場合

私の場合、vagrant起動時に次のようなエラーが出ました。

The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!

/sbin/ifdown 'eth1' || true
/sbin/ip addr flush dev 'eth1'
# Remove any previous network modifications from the interfaces file
sed -e '/^#VAGRANT-BEGIN/,$ d' /etc/network/interfaces > /tmp/vagrant-network-interfaces.pre
sed -ne '/^#VAGRANT-END/,$ p' /etc/network/interfaces | tac | sed -e '/^#VAGRANT-END/,$ d' | tac > /tmp/vagrant-network-interfaces.post
cat \
  /tmp/vagrant-network-interfaces.pre \
  /tmp/vagrant-network-entry \
  /tmp/vagrant-network-interfaces.post \
  > /etc/network/interfaces
rm -f /tmp/vagrant-network-interfaces.pre
rm -f /tmp/vagrant-network-entry
rm -f /tmp/vagrant-network-interfaces.post

/sbin/ifup 'eth1'

Stdout from the command:



Stderr from the command:

bash: line 5: /sbin/ifdown: No such file or directory
bash: line 19: /sbin/ifup: No such file or directory
console
vagrant ssh
# 以降の作業はVM内で行う
sudo apt-get install ifupdown
exit

# ローカルマシン側で作業
vagrant reload

こちら を参考にさせていただきました。

簡単な説明

ルーティング

こ↑こ↓ をベースにroutes/web.phpを修正しました。
基本的にルーティングはLaravelではなくVue側に丸投げする感じで。
余談ですが恐らくVueルーティングより前にLaravel側のルーティングを記述すれば、例えばログインやランディングページだけはbladeファイルを利用して、その他のアプリケーション部分はVueで処理して、的なことができるはずです。

SPAのテンプレート画面作成

基本的にはresources/views/layouts/app.blade.phpをテンプレートとするが、あくまでも入り口だけ。
内部的なコンポーネントは全てVue側で捌く。

Vue側

resources
+--assets
   +--js
   |   `--*chart                # Chart Templates
   |      +--*DoughnutChart.js
   |      `--*LineChart.js
   +--components                # Vue components
   |  +--*SampleChart.vue
   |  `--*Chart.vue
   +--*app.js
   +--*bootstrap.js             # 起動時の設定とか諸々?
   `--*routes.js                # 今回作成。ルートを記述

*つけてるのが変更したファイルです。

Sample-1

2018-05-08_17h02_09.png

まずは簡単な構成から。
chart.jsでできることを無理やりvue-chartjsにさせてる感あるけどお茶を濁しておきます。
基本的なチャートを描く場合、他のVueファイルと違ってtemplateの記述が不要とのこと。ここで躓きました。
また、chart.jsであればcanvasを用意してそこにデータを流し込んで...って手続きが必要だったのが、それも必要ないとのこと。
最終的にはグラフテンプレートを作って後からAPIやら何やらでデータを流し込む、って形になります。

resources/assets/js/components/SampleChart.vue
<script>
// ここでチャートの種類を選択して...
import { Bar } from 'vue-chartjs'
/**
 * Bar       : 棒グラフ
 * Line      : 折れ線グラフ
 * Doughnut  : ドーナツグラフ
 * Pie       : 円グラフ
 * Radar     : レーダーグラフ
 * Polararea : 極域グラフ
 * Bubble    : バブルグラフ
 * Scatter   : 散布図(mixinでは未対応とのこと)
 **/
export default {
  extends: Bar,
  mounted () {
    // データを流し込むだけ
    this.renderChart({
      labels: ['data-1','data-2','data-3'],
      datasets: [{
        label: 'sample',
        backgroundColor: ['#ddd', '#bbb', "#999S"],
        data: [300, 400, 150],
      }]
    })
  }
}
</script>

ちなみにデータセットについては 公式 のほうが詳しいのでそちらをご参照ください。

Sample-2

2018-05-08_17h38_27.gif

いよいよここからVueの恩恵を感じていきます。
まずはresources/assets/js/chart内にチャートのテンプレートを作成します。
ここはjsのみで記述するため、拡張子は.jsで大丈夫です。

その後、resources/assets/js/components/Chart.vueから呼び出してチャートを利用します。

resources/assets/js/components/Chart.vue
<template>
  <div class="small">
    <h1>vue-chartjs</h1>
    <div class="half">
      <!-- :chart-dataでバインディングを行う。多分オプションとかもバインディングできる? -->
      <doughnut-chart :chart-data="doughnutcollection"></doughnut-chart>
    </div>
    <div class="half">
      <line-chart :chart-data="datacollection"></line-chart>
    </div>
    <div>
      <input type="text" v-model="lines">
      <button @click="fillData()">Repaint</button>
      <button @click="randomize()">Randomize</button>
    </div>
  </div>
</template>

<script>
import LineChart from   '../chart/LineChart.js'
import DoughnutChart from '../chart/DoughnutChart.js'

export default {
  components: {
    // ここで読んだコンポーネントをケバブケースにしたら普通に使えるっぽい
    LineChart,     /* <line-chart></line-chart> */
    DoughnutChart, /* <doughnut-chart></doughnut-chart> */

  },
  data () {
    return {
      datacollection: null,
      doughnutcollection: null,
      lines: 3,
    }
  },
  mounted () {
    this.fillData()
  },
  methods: {
    /**
     * 入力されたデータの数に応じてランダムなチャートデータを作成する
     */
    fillData () {
      var datasets = []
      var dDatasets = []
      var labels = []
      var val = 0
      var dLabels = []
      var dColors = []
      var min = 0
      var max = 0
      var loopCnt = this.lines
      for (var i = 0; i < loopCnt;i++) {
        labels = [this.getRandomInt(), this.getRandomInt()]

        if (max < labels[0]) {
          max = labels[0]
        }
        if (max < labels[1]) {
          max = labels[1]
        }

        datasets.push({
          label: 'data-' + (i + 1),
          backgroundColor: 'rgba(255,100,100,0.1)',
          data: labels,
        })

        dLabels.push('data-' + (i + 1))
        dDatasets.push(this.getRandomInt())
        var code = i * 20
        dColors.push('rgba(255,'+code+','+code+',0.4)')
      }
      this.datacollection = {
        labels: [min, max],
        datasets: datasets
      }
      this.doughnutcollection = {
        labels: dLabels,
        datasets: [
        {
          data: dDatasets,
          backgroundColor: dColors
        }
        ]
      }
    },
    /**
     * 1~10の間で適当にグラフデータ数を設定する
     */
    randomize () {
      this.lines = Math.floor(Math.random() * 10) + 1;
      this.fillData();
    },
    getRandomInt () {
      return Math.floor(Math.random() * (50 - 5 + 1)) + 5
    }
  }
}
</script>

<style>
.small {
  margin:  100px auto;
}
.half {
  width: 45%;
  display: inline-block;
}
</style>

ここ辺りで力尽きましたが、こんな感じでリアクティブにチャートを描画できる素晴らしさが伝わったんじゃないかと思います。

備忘録:環境構築までの完全な手順

console
composer create-project laravel/laravel chart "5.5.*"
cd chart

composer require laravel/homestead --dev
vendor/bin/homestead make
# Mac / Linux
# php vendor/bin/homestead make

npm install
# 環境によっては以下のオプションを付ける必要がある場合もある
# npm install --no-bin-links

# もしうまくいかない場合は次のコマンドを実行する
# フォルダーとキャッシュ消してnpmのバージョン上げてる
# rm -rf node_modules
# npm cache clean --force
# npm install -g npm

# その他パッケージのインストールなど
npm i -g cross-env
npm i vue-cli
npm i chart.js     # 基本的にはvue-chartjsをインストールしたらついてくるはず
npm i vue-chartjs

vagrant up

参考

19
18
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
19
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?