Edited at

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

More than 1 year has passed since last update.


はじめに

もう一度、自分なりに最初っから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



参考