本記事では Vue.js v3とTypeScriptを使用して、面グラフ (Area Chart) を作成する方法を紹介します。vue3-charts
ライブラリを活用し、TypeScript を有効にした Vue3 プロジェクト において、簡単に グラフ を追加する方法を ステップバイステップ で説明します。実装にあたり必要となる エラーハンドリング から スタイリング、 インタラクティブ な要素の追加まで、実践的な アプローチ を通じて Vue3 での グラフ作成を実現していこうと思います。
本記事では 面グラフ (Area Chart) に関する コンポーネント 部分についてのみ説明するため、前提となる プロジェクト の概要については、以下の記事を参考にしてください。
面グラフ コンポーネント 作成
面グラフ (Area Chart) を components/AreaChart.vue
に実装してきます。Area Chart に関しては 公式からベースとなるコードが提供されていますので、これを ベース に TypeScript で動作するようにしていきます。
<scirpt>
, <template>
の順番だけ、Vue3 with TypeScript のお作法に従って修正した コンポーネント は以下の通りです。
<script lang="ts">
import { defineComponent, ref } from 'vue'
import { Chart, Grid, Line } from 'vue3-charts'
import { plByMonth } from '@/data'
export default defineComponent({
name: 'LineChart',
components: { Chart, Grid, Line },
setup() {
const data = ref(plByMonth)
const direction = ref('horizontal')
const margin = ref({
left: 0,
top: 20,
right: 20,
bottom: 0
})
const axis = ref({
primary: {
type: 'band'
},
secondary: {
domain: ['dataMin', 'dataMax + 100'],
type: 'linear',
ticks: 8
}
})
return { data, direction, margin, axis }
}
})
</script>
<template>
<Chart
:size="{ width: 500, height: 420 }"
:data="data"
:margin="margin"
:direction="direction"
:axis="axis">
<template #layers>
<Grid strokeDasharray="2,2" />
<Area :dataKeys="['name', 'pl']" type="monotone" :areaStyle="{ fill: 'url(#grad)' }" />
<Line
:dataKeys="['name', 'pl']"
type="monotone"
:lineStyle="{
stroke: '#9f7aea'
}"
/>
<Marker v-if="marker" :value="1000" label="Mean." color="green" strokeWidth="2" strokeDasharray="6 6" />
<defs>
<linearGradient id="grad" gradientTransform="rotate(90)">
<stop offset="0%" stop-color="#be90ff" stop-opacity="1" />
<stop offset="100%" stop-color="white" stop-opacity="0.4" />
</linearGradient>
</defs>
</template>
<template #widgets>
<Tooltip
borderColor="#48CAE4"
:config="{
pl: { color: '#9f7aea' },
avg: { hide: true },
inc: { hide: true }
}"
/>
</template>
</Chart>
</template>
ただし、この状態でいくつか エラー が出ています。次の セクション では、まずこれらに対処していきます。
AreaChart.vue エラー 対処
Chart コンポーネントプロパティ (direction) 修正
以下の箇所で、 TS2322
エラー が発生しています。
AreaChart.vue
<Chart :size="{ width: 500, height: 420 }" :data="data" :margin="margin" :direction="direction" :axis="axis">
エラー 内容は以下の通り
Type 'string' is not assignable to type 'Direction | undefined'.ts(2322)
LineChart.vue
, BarChart.vue
でも同様の エラー でしたので、AreaChart.vue
でも同様の対処を実施していきます。
AreaChart.vue
Ref
の インポート を追加します
import { defineComponent, ref, Ref } from 'vue'
Direction
型 を vue3-charts
ライブラリからインポートします
import { Direction } from 'vue3-charts/src/types'
defineComponent
の setup()
で、 d
irection を Direction
型として設定します。
setup() {
const data = ref(plByMonth)
const direction: Ref<Direction> = ref('horizontal')
Chart コンポーネントプロパティ (axis) 修正
direction
と同様に、 Chart
コンポーネント 設定部分で axis
プロパティ にも エラー が発生しています。
AreaChart.vue
<Chart :size="{ width: 500, height: 420 }" :data="data" :margin="margin" :direction="direction" :axis="axis">
エラー 内容は以下のとおりです。
Type '{ primary: { type: string; }; secondary: { domain: string[]; type: string; ticks: number; }; }' is not assignable to type 'ChartAxis'.ts(2322)
axis
プロパティ の エラー も LineChart.vue
と同じ内容ですので、同様に対処していきます。
AreaChart.vue
ChartAxis
型 を vue3-charts
ライブラリからインポートします
import { Direction, ChartAxis } from 'vue3-charts/src/types'
defineComponent
の setup()
で、 axis を ChartAxis
型として設定します。
const axis: Ref<ChartAxis> = ref({
ChartAxis
型に必要な primary/domain
プロパティ を追加します。
const axis: Ref<ChartAxis> = ref({
primary: {
domain: ['dataMin', 'dataMax'],
type: 'band'
},
secondary: {
domain: ['dataMin', 'dataMax + 100'],
type: 'linear',
ticks: 8
}
})
Area コンポーネント 追加
ベースのコード をよく見ると、 Area
コンポーネント が インポート されていませんので、 Area
コンポーネント を利用可能にしていきます。
AreaChart.vue
Area
コンポーネント を vue3-charts
からインポートします
import { Chart, Grid, Line, Area } from 'vue3-charts'
defineComponent
で、Area
コンポーネント を 登録します。 また合わせて、 defineComponent
の name
を LineChart
から AreaChart
に変更しておきます。
export default defineComponent({
name: 'AreaChart',
components: { Chart, Grid, Line, Area },
Marker コンポーネント 修正
Area Chart (面グラフ) 自体ではありませんが、 ベースとなるコード には Marker
サブコンポーネント が定義されています。 ただし、以下の エラー が発生しているため、対応していきます。
AreaChart.vue
エラー が発生しているのは以下の箇所です。
<Marker v-if="marker" :value="1000" label="Mean." color="green" strokeWidth="2" strokeDasharray="6 6" />
エラー の内容は以下のようなものです。
Property 'marker' does not exist on type '{ $: ComponentInternalInstance; $data: {}; $props: Partial<{}> & Omit<{} & VNodeProps & AllowedComponentProps & ComponentCustomProps & Readonly<...>, never>; ... 10 more ...; $watch<T extends string | ((...args: any) => any)>(source: T, cb: T extends (...args: any) => infer R ? (args_0: R, args_1: R) => any : (...ar...'.ts(2339)
ベースとなるコード をよく見ると、 <template>
で 定義している Marker
コンポーネント が インポート されていませんので、 Area
コンポーネント 同様の対処をしていきます。
AreaChart.vue
Marker
コンポーネント を vue3-charts
からインポートします
import { Chart, Grid, Marker, Line, Area } from 'vue3-charts'
defineComponent
で Marker
コンポーネント を 登録します。
export default defineComponent({
name: 'AreaChart',
components: { Chart, Grid, Marker, Line, Area },
Marker
コンポーネント の プロパティ で v-if="marker"
を用いていますが、 marker
という変数は使われていないので、削除します。 また、strokeWidth
箇所で以下の エラー が発生しています。
Type 'string' is not assignable to type 'number'.ts(2322)
strokeWidth
は 値を数値として渡す必要があるため、 v-bind
を用いて :strokeWidth="10"
と記載することで数値を渡せるようになり、 エラー を解消することができます。
<Marker :value="1000" label="Mean." color="green" :strokeWidth="2" strokeDasharray="6 6" />
Tooltip 対応
ベースとなるコード の <template>
には Tooltip
コンポーネントの記載がありますが、 インポート されていないため表示されていません。 以下の修正を加えて、 Tooltip
が表示されるようにしていきます。
AreaChart.vue
Tooltip
コンポーネント を vue3-charts
からインポートします
import { Chart, Grid, Tooltip, Marker, Line, Area } from 'vue3-charts'
あわせて、 defineComponent
の components
に Tooltip
を登録します。
export default defineComponent({
name: 'AreaChart',
components: { Chart, Grid, Tooltip, Marker, Line, Area },
ここまでの修正を終えた状態で プロジェクト を実行すると、以下のような グラフ が表示されるようになります。
データポイント に カーソル をあわせることで Tooltip が表示されます。
eslint エラー 定義済み名称 への 対処 (Marker, Line, Area)
ここでは 発生している eslint
エラー に対処していきます。今回利用した コンポート名 Marker
, Line
, Area
は プログラム 今回のような 小さなプロジェクト では問題になることはありませんが、HTML 標準 として規定されている名称の コンポーネント は使うべきではないため、as
を用いて 別名で利用することにします。
AreaChart.vue
以下の箇所で eslint
エラー が発生しています。
export default defineComponent({
name: 'AreaChart',
components: { Chart, Grid, Marker, Line, Area },
エラー の内容は以下のとおりです。
Name "Marker" is reserved.eslintvue/no-reserved-component-names
同じ エラー が Line
, Area
にも出ています。 予約済みの名称と重複してしまっているため別名を用いることが推奨されています。それぞれ ChartMarker
, LineChartComponent
, AreaChartComponent
という別名で インポートしていきます。
import {
Chart, Grid,
Marker as ChartMarker,
Line as LineChartComponent,
Area as AreaChartComponent
} from 'vue3-charts'
あわせて、 defineComponent
も更新します。
export default defineComponent({
name: 'AreaChart',
components: {
Chart, Grid, Tooltip,
ChartMarker, LineChartComponent, AreaChartComponent
},
テンプレート にも更新した コンポーネント名称を反映していきます。
<template>
<Chart :size="{ width: 500, height: 420 }" :data="data" :margin="margin" :direction="direction" :axis="axis">
<template #layers>
<Grid strokeDasharray="2,2" />
<AreaChartComponent :dataKeys="['name', 'pl']" type="monotone" :areaStyle="{ fill: 'url(#grad)' }" />
<LineChartComponent :dataKeys="['name', 'pl']" type="monotone" :lineStyle="{
stroke: '#9f7aea'
}" />
<ChartMarker :value="1000" label="Mean." color="green" :strokeWidth="2" strokeDasharray="6 6" />
<defs>
<linearGradient id="grad" gradientTransform="rotate(90)">
<stop offset="0%" stop-color="#be90ff" stop-opacity="1" />
<stop offset="100%" stop-color="white" stop-opacity="0.4" />
</linearGradient>
</defs>
</template>
<template #widgets>
<Tooltip borderColor="#48CAE4" :config="{
pl: { color: '#9f7aea' },
avg: { hide: true },
inc: { hide: true }
}" />
</template>
</Chart>
</template>
面グラフ の カスタマイズ
ここまでで、 ベースとなるコード を使って 面グラフ が描画されるようになりました。 この セクション では、 面グラフ を少し カスタマイズ してみます。
純粋な 面グラフ だけ表示
ベースとなるコード は Area
, Line
が併用されている形ですが、 Area
だけの シンプル な構成の見た目を確認してみます。 ここでは LineChartComponent
や ChartMarker
を削除して 純粋に 面グラフ だけを表示した状態から カスタマイズしていきます。
AreaChart.vue
<AreaChartComponent :dataKeys="['name', 'pl']" type="monotone" :areaStyle="{ fill: 'url(#grad)' }" />
<!-- <LineChartComponent :dataKeys="['name', 'pl']" type="monotone" :lineStyle="{
stroke: '#9f7aea'
}" /> -->
<!-- <ChartMarker :value="1000" label="Mean." color="green" :strokeWidth="2" strokeDasharray="6 6" /> -->
データポイント に カーソル を合わせると ツールチップ が表示された 純粋な 面グラフ が表示されていることがわかります。
以降の セクション では Area
コンポーネント の プロパティ に注目して、いくつかの カスタマイズ を実際に施していきます。
areaStyle プロパティ(面の塗りつぶし)
AreaChartComponent
の areaStyle
を設定することで 面グラフ の 色合い などを変更することができます。
AreaChart.vue
ベースとなるコード では "{ fill: 'url(#grad)' }"
という値が指定されています。
<AreaChartComponent :dataKeys="['name', 'pl']" type="monotone" :areaStyle="{ fill: 'url(#grad)' }" />
この場合、 以下の箇所で詳細な設定を指定することになります。
<defs>
<linearGradient id="grad" gradientTransform="rotate(90)">
<stop offset="0%" stop-color="#FF6347" stop-opacity="1" />
<stop offset="100%" stop-color="white" stop-opacity="0.4" />
</linearGradient>
</defs>
単色塗りつぶし
まずは最も シンプル な形でみていきます。
AreaChart.vue
面グラフ を赤で塗りつぶしてみます。
<AreaChartComponent :dataKeys="['name', 'pl']" type="monotone" :areaStyle="{ fill: 'red' }" />
グラデーション
ベースとなるコード は最初から少し応用編といってもよい グラデーション塗りつぶし が実装されています。 これを少し カスタマイズ してみます。
AreaChart.vue
仕組みとしては、 #grad
という形で linearGardient
を定義する形です。
<AreaChartComponent :dataKeys="['name', 'pl']" type="monotone" :areaStyle="{ fill: 'url(#grad)' }" />
<defs>
<linearGradient id="grad" gradientTransform="rotate(90)">
<stop offset="0%" stop-color="#be90ff" stop-opacity="1" />
<stop offset="100%" stop-color="white" stop-opacity="0.4" />
</linearGradient>
</defs>
offset | |
stop-color | |
stop-opacity | |
以降では、 linearGradient
の値を変化させて カスタマイズ させていきます。
単色 グラデーション
AreaChart.vue
同一色でグラデーションさせてみます。透明度 (stop-opacity
) を変化させることで実現します。
<defs>
<linearGradient id="grad" gradientTransform="rotate(90)">
<stop offset="0%" stop-color="red" stop-opacity="1" />
<stop offset="100%" stop-color="red" stop-opacity="0.2" />
</linearGradient>
</defs>
月毎にグラデーションされるのではなく、全体のなかで大きな値が最も濃くなる点が特徴です。
2色 グラデーション
AreaChart.vue
緑黄色、赤でグラデーションさせてみます。 stop offset
ごとの stop-color
を変えることで実現します。
<defs>
<linearGradient id="grad" gradientTransform="rotate(90)">
<stop offset="0%" stop-color="green" stop-opacity="1" />
<stop offset="100%" stop-color="red" stop-opacity="0.4" />
</linearGradient>
</defs>
今回のように、突出したデータがあるとグラデーションの効果が出にくいかもしれません。
3色 グラデーション
AreaChart.vue
緑と赤とでグラデーションさせてみます。中間色として stop offset="50%"
のデータを追加することで実現します。なお、わかりやすいように、 透明度は全て 1 にしています。
<defs>
<linearGradient id="grad" gradientTransform="rotate(90)">
<stop offset="0%" stop-color="green" stop-opacity="1" />
<stop offset="50%" stop-color="yellow" stop-opacity="1" />
<stop offset="100%" stop-color="red" stop-opacity="1" />
</linearGradient>
</defs>
今回のように、突出したデータがある場合は、2色より3色の方がメリハリが効きそうですね。
style プロパティ(面の形)
ここでは style
プロパティ を用いて 面グラフ の形を カスタマイズ していきます。 単色塗り の 面グラフ を基にしていきます。 なお、style
を指定しない場合は デフォルトとして normal
が採用されます。 指定できる スタイル は 以下の 4種類 です。
normal
AreaChart.vue
以下のように type="normal"
とすることで、monotone
に比べ、緩やかなカーブを描く 面グラフとなります。 傾向を強調した形 と言ってもいいかもしれません。
<AreaChartComponent :dataKeys="['name', 'pl']" type="normal" :areaStyle="{ fill: 'red' }" />
monotone
AreaChart.vue
以下のように type="monotone"
とすることで、カーブを描いた 面グラフ となります。 公式
<AreaChartComponent :dataKeys="['name', 'pl']" type="monotone" :areaStyle="{ fill: 'red' }" />
step
AreaChart.vue
以下のように type="step"
とすることで、階段状の 面グラフ となります。
<AreaChartComponent :dataKeys="['name', 'pl']" type="step" :areaStyle="{ fill: 'red' }" />
natural
AreaChart.vue
以下のように type="natural"
とすることで、monotone
に比べ、緩やかなカーブを描く 面グラフとなります。 傾向を強調した形 と言ってもいいかもしれません。
<AreaChartComponent :dataKeys="['name', 'pl']" type="natural" :areaStyle="{ fill: 'red' }" />
まとめ
Vue3 と TypeScript での 面グラフ 作成における解説はここまでです。vue3-charts
を用いた 面グラフ の実装から、エラー対処、カスタマイズ、といったさまざまな技術を探求してきました。これらの知識を活用し、あなたのプロジェクトに魅力的なビジュアルを加えてみてください。
TS2322
に対処する
必要な コンポーネント Area
, Tooltip
, Marker
を追加する
style
, areaStyle
プロパティ を駆使して カスタマイズする