環境
このページで使用しているフレームワークやライブラリのバージョンは、以下のとおりです。
vue.js | 3.2.31 |
vue3-sfc-loader | 0.8.4 |
chart.js | 3.6.0 |
Chart.jsとは?
「Chart.js」は、チャート(グラフ)を表示するJavaScriptライブラリです。
機能の豊富さと表示の美しさで、この「Chart.js」を越えるJavaScriptライブラリはないと思います。
MITライセンスで、無償で利用できます。
2021年の4月に、メジャーバージョンが「2.x」から「3.x」に変わり、仕様も大きく変わっています。
なので、今から「Chart.js」を利用する方は、バージョン「3.x」を使うことをお勧めします。
Vue3で「Chart.js」を使えるようにしたコンポーネント「vue-chartjs」もあります。
「vue-chartjs」のバージョン「4.x」から、「Chart.js」のバージョン「3.x」に対応しているので、Vueの環境で簡単に「Chart.js」を使いたい場合は、「vue-chartjs」を利用すると良いでしょう。
ただし、「vue-chartjs」のバージョン「4.0.5」では、ドキュメントに以下の記載があり、チャートのOptionsを変更しても、チャートが再描画されません。
Options
The options object is not currently implemented reactively. Therefore, if you dynamically change the chart options, they will not be recognized by the update data handler.
なので、この記事では「vue-chartjs」を使わず、「Chart.js」を直接ラップしたSFCを作成し、このコンポーネントでチャートを表示します。
WordPressの投稿にVueのSFCを読み込む方法については、以下の記事で紹介しています。
棒グラフを表示する
まずは、簡単な棒グラフを表示してみましょう。
このチャートは、「Chart.js」のドキュメントの最初の例に出てくる棒グラフです。
チャートが表示されている部分には、WordPressのブロックエディタで以下の「カスタム HTML」ブロックを配置しています。
<script src="https://cdn.jsdelivr.net/npm/vue@3.2.31/dist/vue.global.js"></script>
<div id="app"></div>
<script type="module">
////////////////////////////////////////////////////////////////////////////////
// vue3-sfc-loader モジュール
////////////////////////////////////////////////////////////////////////////////
import { loadModule } from "https://cdn.jsdelivr.net/npm/vue3-sfc-loader@0.8.4/dist/vue3-sfc-loader.esm.js";
////////////////////////////////////////////////////////////////////////////////
// vue3-sfc-loader オプション
// SFCファイルから外部のモジュールをimportできるオプション
// 参考:https://github.com/FranckFreiburger/vue3-sfc-loader/issues/14#issuecomment-908849863
////////////////////////////////////////////////////////////////////////////////
const vue3_sfc_loader_options = {
moduleCache: { vue: Vue },
getFile(url) {
url = /.*?\.js|.mjs|.css|.less|.vue$/.test(url)
? url
: `${url}.vue`;
const type = /.*?\.js|.mjs$/.test(url)
? ".mjs"
: /.*?\.vue$/.test(url)
? ".vue"
: /.*?\.css$/.test(url)
? ".css"
: ".vue";
const getContentData = (asBinary) =>
fetch(url).then((res) =>
!res.ok
? Promise.reject(url)
: asBinary
? res.arrayBuffer()
: res.text()
);
return { getContentData: getContentData, type: type };
},
addStyle(textContent) {
let styleElement = document.createElement("style");
document.head.insertBefore(
Object.assign(styleElement, { textContent }),
document.head.getElementsByTagName("style")[0] || null
);
},
handleModule(type, getContentData, path, options) {
switch (type) {
case ".css":
return options.addStyle(getContentData(false));
case ".less":
console.error(".......");
}
},
log(type, ...args) {
console.log(type, ...args);
},
};
////////////////////////////////////////////////////////////////////////////////
// Vue.js アプリケーションインスタンス
////////////////////////////////////////////////////////////////////////////////
const app = Vue.createApp({
components: {
"bar-chart": Vue.defineAsyncComponent(() =>
loadModule(
"../wp-content/themes/cocoon-child-master/vue-components/bar_chart.vue",
vue3_sfc_loader_options
)
),
},
template: `<bar-chart />`,
});
app.mount("#app");
</script>
コードの解説
前回の紹介記事「ブラウザ環境でVue3の単一ファイルコンポーネントを使う」からの差分を中心に解説します。
////////////////////////////////////////////////////////////////////////////////
// Vue.js アプリケーションインスタンス
////////////////////////////////////////////////////////////////////////////////
const app = Vue.createApp({
components: {
"bar-chart": Vue.defineAsyncComponent(() =>
loadModule(
"../wp-content/themes/cocoon-child-master/vue-components/bar_chart.vue",
vue3_sfc_loader_options
)
),
},
template: `<bar-chart />`,
});
app.mount("#app");
アプリケーションインスタンスの作成とマウントの方法は、前回の「ブラウザ環境でVue3の単一ファイルコンポーネントを使う」と同じ流れです。
違うのは、"bar_chart.vue"というSFCを"bar-chart"という名前のコンポーネントとして読み込んで、`<bar-chart />`で表示している点です。
"bar_chart.vue"の中身
"bar_chart.vue"の全体です。
<script setup>
////////////////////////////////////////////////////////////////////////////////
// Chart.js モジュール
////////////////////////////////////////////////////////////////////////////////
// Chart.jsモジュールのimportとregisterを行う
import { Chart, registerables } from "../chart.js-3.6.0/dist/chart.esm.js";
Chart.register(...registerables);
////////////////////////////////////////////////////////////////////////////////
// data
////////////////////////////////////////////////////////////////////////////////
let chart = {}; // チャートオブジェクト
const chart_height = 400; // チャートの高さ
let chart_options = { // チャートのオプション
scales: {
y: {
beginAtZero: true
}
},
};
let chart_data = { // チャートのデータ
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: "# of Votes",
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
"rgba(255, 99, 132, 0.2)",
"rgba(54, 162, 235, 0.2)",
"rgba(255, 206, 86, 0.2)",
"rgba(75, 192, 192, 0.2)",
"rgba(153, 102, 255, 0.2)",
"rgba(255, 159, 64, 0.2)"
],
borderColor: [
"rgba(255, 99, 132, 1)",
"rgba(54, 162, 235, 1)",
"rgba(255, 206, 86, 1)",
"rgba(75, 192, 192, 1)",
"rgba(153, 102, 255, 1)",
"rgba(255, 159, 64, 1)"
],
borderWidth: 1
}]
};
////////////////////////////////////////////////////////////////////////////////
// onMountedライフサイクルフック
////////////////////////////////////////////////////////////////////////////////
Vue.onMounted(() => {
renderChart();
});
////////////////////////////////////////////////////////////////////////////////
// チャートを描画する
////////////////////////////////////////////////////////////////////////////////
const renderChart = () => {
const ctx = document.getElementById("chart").getContext("2d");
chart = new Chart(ctx, {
type: "bar",
data: chart_data,
options: chart_options,
});
};
</script>
<template>
<div>
<canvas id="chart" width="100%" v-bind:height="chart_height"></canvas>
</div>
</template>
<style>
</style>
"bar_chart.vue"のセットアップは、
<script>
export default defineComponent({
setup() {
…
},
});
</script>
を使わずに、
<script setup>
…
</script>
の中でやっています。
<script setup>については、Vue3の公式ドキュメント「SFC<script setup>」を参照してください。
<script setup>の利便性については、以下の記事が参考になります。
////////////////////////////////////////////////////////////////////////////////
// Chart.js モジュール
////////////////////////////////////////////////////////////////////////////////
// Chart.jsモジュールのimportとregisterを行う
import { Chart, registerables } from "../chart.js-3.6.0/dist/chart.esm.js";
Chart.register(...registerables);
「Chart.js」ライブラリ一式をCDNサイト「https://www.jsdelivr.com/package/npm/chart.js」からダウンロードして、適当なフォルダに保存します。
「ちょいプラ素材」のブログは、WordPressのテーマに「Cocoon」を使っています。
今回は、「Cocoon」の子テーマ「cocoon-child-master」の下に"chart.js-3.6.0"というフォルダを作って保存しました。
SFC"bar_chart.vue"が保存されているフォルダからの相対パス"../chart.js-3.6.0/dist/chart.esm.js"で「Chart.js」のESモジュール"chart.esm.js"をインポートします。
「Chart.js」モジュールをインポートした後は、実際に利用するモジュールの登録(register)が必要です。1つ1つのモジュールを登録するのは面倒なので、"Chart.register(...registerables);"でまとめて登録しています。
////////////////////////////////////////////////////////////////////////////////
// data
////////////////////////////////////////////////////////////////////////////////
let chart = {}; // チャートオブジェクト
const chart_height = 400; // チャートの高さ
let chart_options = { // チャートのオプション
…
};
let chart_data = { // チャートのデータ
…
};
このSFCだけで使うデータを宣言しています。
それぞれのデータの意味は、コメントを見てください。
////////////////////////////////////////////////////////////////////////////////
// onMountedライフサイクルフック
////////////////////////////////////////////////////////////////////////////////
Vue.onMounted(() => {
renderChart();
});
このSFCがマウントされたときに呼ばれる、ライフサイクルフックです。
SFCがマウントされたら、この後に説明する"renderChart();"を実行します。
////////////////////////////////////////////////////////////////////////////////
// チャートを描画する
////////////////////////////////////////////////////////////////////////////////
const renderChart = () => {
const ctx = document.getElementById("chart").getContext("2d");
chart = new Chart(ctx, {
type: "bar",
data: chart_data,
options: chart_options,
});
};
チャートを描画する処理です。
この後の<template>タグで配置される<canvas id="chart">要素に「Chart.js」の"bar"モジュール(棒グラフモジュール)を紐づけます。
また、"chart = new Chart();"で作成した「Chart.js」のモジュール(JavaScriptのオブジェクト)を変数"chart"に保存しておきます。
こうすることで、「Chart.js」のメソッド(関数)を使って、作成した"bar"モジュールを操作することができます。
<template>
<div>
<canvas id="chart" width="100%" v-bind:height="chart_height"></canvas>
</div>
</template>
<template>タグで<canvas id="chart">要素を配置します。
ユーザーインターフェースで棒グラフを操作する
次に、先ほどの棒グラフを表示するSFCにユーザーインターフェースを追加して、チャートを操作してみましょう。
ユーザーインターフェースとデータの連携は、Vueが得意とするところです。
[データを変更]ボタンを押すと、データが0~50の範囲の整数にランダムに変化します。
[縦軸の最大値]スライダーを動かすと、チャートの縦軸の最大値を変更できます。
"bar_chart_with_ui.vue"の中身
新しく作成したSFC"bar_chart_with_ui.vue"の全体です。
<script setup>
////////////////////////////////////////////////////////////////////////////////
// Chart.js モジュール
////////////////////////////////////////////////////////////////////////////////
// Chart.jsモジュールのimportとregisterを行う
import { Chart, registerables } from "../chart.js-3.6.0/dist/chart.esm.js";
Chart.register(...registerables);
////////////////////////////////////////////////////////////////////////////////
// data
////////////////////////////////////////////////////////////////////////////////
let chart = {}; // チャートオブジェクト
const chart_height = 400; // チャートの高さ
let y_max = Vue.ref(50); // 縦軸の最大値
let chart_options = { // チャートのオプション
scales: {
y: {
beginAtZero: true,
min: 0,
max: y_max.value,
}
},
};
let chart_data = { // チャートのデータ
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: "# of Votes",
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
"rgba(255, 99, 132, 0.2)",
"rgba(54, 162, 235, 0.2)",
"rgba(255, 206, 86, 0.2)",
"rgba(75, 192, 192, 0.2)",
"rgba(153, 102, 255, 0.2)",
"rgba(255, 159, 64, 0.2)"
],
borderColor: [
"rgba(255, 99, 132, 1)",
"rgba(54, 162, 235, 1)",
"rgba(255, 206, 86, 1)",
"rgba(75, 192, 192, 1)",
"rgba(153, 102, 255, 1)",
"rgba(255, 159, 64, 1)"
],
borderWidth: 1
}]
};
////////////////////////////////////////////////////////////////////////////////
// onMountedライフサイクルフック
////////////////////////////////////////////////////////////////////////////////
Vue.onMounted(() => {
renderChart();
});
////////////////////////////////////////////////////////////////////////////////
// チャートを描画する
////////////////////////////////////////////////////////////////////////////////
const renderChart = () => {
const ctx = document.getElementById("chart2").getContext("2d");
chart = new Chart(ctx, {
type: "bar",
data: chart_data,
options: chart_options,
});
};
////////////////////////////////////////////////////////////////////////////////
// チャートのデータを変更する
////////////////////////////////////////////////////////////////////////////////
const onChangeData = () => {
chart_data.datasets[0].data = [
Math.floor(Math.random() * 51),
Math.floor(Math.random() * 51),
Math.floor(Math.random() * 51),
Math.floor(Math.random() * 51),
Math.floor(Math.random() * 51),
Math.floor(Math.random() * 51),
];
chart.update(); // チャートを再描画する
};
////////////////////////////////////////////////////////////////////////////////
// 縦軸の最大値を変更する
////////////////////////////////////////////////////////////////////////////////
const onChangeYMax = () => {
chart_options.scales.y.max = y_max.value;
chart.update(); // チャートを再描画する
};
</script>
<template>
<div>
<canvas id="chart2" width="100%" v-bind:height="chart_height"></canvas>
<form class="chart-ui-form">
<input type="button" class="data-change-button" v-on:click="onChangeData" value="データを変更" />
<div class="chart-range-container">
<span style="margin-right: 0.2em">縦軸の最大値 10</span>
<input type="range" id="view-time-start-range" class="y-max-range" v-model.number="y_max" min="10"
max="100" step="10" v-on:mouseup="onChangeYMax" v-on:touchend="onChangeYMax" />
<span style="margin-left: 0.2em">100</span>
</div>
</form>
</div>
</template>
<style>
.chart-ui-form {
margin: 20px;
}
.chart-range-container {
margin-left: 10px;
margin-top: 10px;
}
.data-change-button {
color: #fff;
background-color: #3b83d8;
font-weight: bold;
border-radius: 4px;
display: inline-block;
cursor: pointer;
line-height: normal;
padding: 7px 13px;
text-decoration: none;
text-align: center;
font-size: 14px;
border: 2px solid transparent;
position: relative;
}
.y-max-range {
max-width: 40%;
width: 40%;
}
</style>
SFCの変更点を解説します。
let y_max = Vue.ref(50); // 縦軸の最大値
let chart_options = { // チャートのオプション
scales: {
y: {
beginAtZero: true,
min: 0,
max: y_max.value,
}
},
};
チャートのオプションを指定する"chart_options"の"scale.y"オブジェクトに、"min"と"max"を追加しました。
"min"、"max"を指定しない場合は、データの値に応じて、「Chart.js」が軸の表示を最適に調整してくれます。
"max"には、新しく追加した変数"y_max"の値を設定します。
また、変数"y_max"は、Vueの「refメソッド」でリアクティブな変数にしています。
////////////////////////////////////////////////////////////////////////////////
// チャートのデータを変更する
////////////////////////////////////////////////////////////////////////////////
const onChangeData = () => {
chart_data.datasets[0].data = [
Math.floor(Math.random() * 51),
Math.floor(Math.random() * 51),
Math.floor(Math.random() * 51),
Math.floor(Math.random() * 51),
Math.floor(Math.random() * 51),
Math.floor(Math.random() * 51),
];
chart.update(); // チャートを再描画する
};
[データを変更]ボタンが押されたときに呼ばれるイベントハンドラーです。
チャートのデータが0~50の範囲の整数にランダムに変化します。
実際の用途では、チャートに表示したいデータの設定処理を実装します。
その後、"chart.update();"でチャートを再描画します。
////////////////////////////////////////////////////////////////////////////////
// 縦軸の最大値を変更する
////////////////////////////////////////////////////////////////////////////////
const onChangeYMax = () => {
chart_options.scales.y.max = y_max.value;
chart.update(); // チャートを再描画する
};
[縦軸の最大値]スライダーを動かした後、マウスのボタンを離すと呼ばれるイベントハンドラーです。
チャートのオプション"chart_options.scales.y.max"の値を変更した後、"chart.update();"でチャートを再描画します。
<template>
…
</template>
<style>
…
</style>
<template>タグと<style>タグで、SFCの外観(ビュー)を定義します。
以上のように、VueのSFCを使うと、
- ユーザーインターフェースの操作をトリガーにして、
- 必要なデータやオプションを変更し、
- 「Chart.js」のupdate()メソッドを呼び出すだけで、
チャートの表示を動的に、しかも簡単に操作できます。
まとめ
「Chart.js」を直接ラップしたSFCを作成し、コンポーネントでチャートを表示する方法を紹介しました。
チャートのデータやオプションを動的に変えることができるので、WordPressのデータベースのデータをビジュアルに表示したり、データが保存されているCSVファイルをアップロードして、CSVファイルのデータをチャートで確認したり、いろいろなシチュエーションで活用できるはずです。
次は、WordPressの投稿に「vue-good-table-next」のテーブルを表示してみましょう。
コメント