Chartjs.Blazorで折れ線グラフ(LineChart)と棒グラフ(BarChart)を混合表示する

# はじめに

![Fig_Top.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604076/460718d8-b6de-ada8-4c1b-bdb5058fcbc8.png)

最近Brazorでの開発をはじめたのですが、
ChartJs.Blazorで折れ線グラフと棒グラフを混合表示しようとしたところハマりました。
結果的には最新バージョン(2.0.0)では混合表示は未対応で、
過去バージョン(1.1.0)ではできることが分かったので、
ChartJs.Blazorの導入から混合表示の方法までを以下記録します。

# 実装環境

|環境           |バージョン|備考|
|---------------|----------|----|
|ASP.NET.Core   |5.0       |----|
|Chartjs.Blazor |1.1.0     |2.0.0ではbarとlineのmix表示ができない為1.1.0を使用[(参照)](https://github.com/mariusmuntean/ChartJs.Blazor/issues/133)|

# Blazorプロジェクトを立ち上げる

下記コマンドをターミナルで実行。
詳細は割愛します。
今回は`ChartDemo`という名前のプロジェクトを作成しました。

```
dotnet new blazorwasm -o ChartDemo
```

# BlazorプロジェクトにChartjs.Blazorを組み込む

下記のようにChartjs.Blazorの[チュートリアル](https://github.com/mariusmuntean/ChartJs.Blazor/blob/v1.1.0/README.md)に沿って環境を構築していきます。

## Chartjs.Blazorインストール

下記コマンドでChartJs.Blazorをインストールします。

```
dotnet add package ChartJs.Blazor
```

ChartDemo.csprojを開いてversionが`1.1.0`とであるかを確認します。
`1.1.0`であれば下記のようなコードが記載されています。

```
<PackageReference Include="ChartJs.Blazor" Version="1.1.0"/>
```

`1.1.0`ではなかった場合はNuGet Package Managerを用いてインストールを行うとバージョンを指定することが出来ます。

## chartjs.Blazorを使用する為の設定

`Index.html`の`<script src="_framework/blazor.webassembly.js"></script>`の下に下記のようにコードを追加します。

```html
<!-- <body>タグの前後は省略 -->
<body>
    <div id="app">Loading...</div>

    <div id="blazor-error-ui">
        An unhandled error has occurred.
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>
    <script src="_framework/blazor.webassembly.js"></script>

    <!-- ※ ここから追加コード -->
    <!-- Reference the included moment.js javascript file. -->
    <script src="_content/ChartJs.Blazor/moment-with-locales.min.js" type="text/javascript" language="javascript"></script>
    <!-- Reference the included ChartJs javascript file. -->
    <script src="_content/ChartJs.Blazor/Chart.min.js" type="text/javascript" language="javascript"></script>
    <!-- This is the glue between the C# code and the ChartJs charts -->
    <script src="_content/ChartJs.Blazor/ChartJsBlazorInterop.js" type="text/javascript" language="javascript"></script>
    <!-- Some styling -->
    <link rel="stylesheet" href="_content/ChartJs.Blazor/ChartJSBlazor.css" />
    <!-- ※ ここまで追加コード -->
</body>
```

`_Imports.razor`に下記のコードを追加します。

```csharp
@using ChartJs.Blazor;
```

# グラフを作成する

Line chartとBar chartを混在させるには、
まずbar chartを作成し、そこにLine chartのDatasetを設定すれば実現できます。
[(参照)](https://github.com/mariusmuntean/ChartJs.Blazor/issues/133)

## コード

今回はグラフ作成の説明用なので画面作成は行わず、
ホーム画面にグラフを張り付けるまでにとどめます。
ということで`Index.razor`を以下のように書換えます。
下記コードは[こちらのBarグラフ](https://github.com/mariusmuntean/ChartJs.Blazor/blob/v1.1.0/samples/Shared/ChartJs.Blazor.Sample.Shared/Components/BarCharts/TimeBarChartComponent.razor)をベースとして、
コメント箇所を変更しています。

```csharp
@page "/"

@using ChartJs.Blazor.ChartJS.BarChart
@using ChartJs.Blazor.ChartJS.BarChart.Axes
@using ChartJs.Blazor.ChartJS.Common.Axes
@using ChartJs.Blazor.ChartJS.Common.Axes.Ticks
@using ChartJs.Blazor.ChartJS.Common.Time
@using ChartJs.Blazor.ChartJS.Common.Enums
@using ChartJs.Blazor.Charts
@using ChartJs.Blazor.ChartJS.Common.Properties
@using ChartJs.Blazor.Util

@* ※ 折れ線グラフをImport *@
@using ChartJs.Blazor.ChartJS.LineChart

<h1>Hello, world!</h1>

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />

<h1>Time Bar Chart</h1>

<ChartJsBarChart @ref="_barChartJs" Config="@_config" Width="600" Height="300" />

@code {
    private BarConfig _config;
    private ChartJsBarChart _barChartJs;

    protected override void OnInitialized()
    {
        _config = new BarConfig
        {
            Options = new BarOptions
            {
                Title = new OptionsTitle
                {
                    Display = true,
                    Text = "Sample chart from Blazor"
                },
                Scales = new BarScales
                {
                    XAxes = new List<CartesianAxis>
                    {
                        new BarTimeAxis
                        {
                            BarPercentage = 0.75,
                            Time = new TimeOptions
                            {
                                Unit = TimeMeasurement.Hour
                            },
                            Offset = true
                        }
                    },
                    YAxes = new List<CartesianAxis>
                    {
                        new BarLinearCartesianAxis
                        {
                            Ticks = new LinearCartesianTicks
                            {
                                BeginAtZero = true
                            }
                        }
                    }
                },
                Responsive = true
            }
        };

        var barSet = new BarDataset<TimeTuple<double>>
        {
            Label = "My time-double dataset",
            BackgroundColor = new[] { ColorUtil.RandomColorString(), ColorUtil.RandomColorString(), ColorUtil.RandomColorString(), ColorUtil.RandomColorString() },
            BorderWidth = 1,
            HoverBackgroundColor = ColorUtil.ColorString(0, 0, 0, 0.1),
            HoverBorderColor = "#020202",
            HoverBorderWidth = 1,
            BorderColor = "#ffffff"
        };

        var now = DateTime.Now;
        var rnd = new Random();
        barSet.AddRange(Enumerable.Range(2, 4).Select(i => new TimeTuple<double>((Moment)now.AddHours(i), rnd.NextDouble() * 4)));
        _config.Data.Datasets.Add(barSet);

        @* ※ 折れ線グラフのデータを作成する *@
        @* ビルドエラーとなるコードをコメントアウト *@
        @* BorderColor(線の色)を変更 *@
        var lineSet = new LineDataset<TimeTuple<double>>
        {
            Label = "My time-double dataset",
            @* BackgroundColor = new[] { ColorUtil.RandomColorString(), ColorUtil.RandomColorString(), ColorUtil.RandomColorString(), ColorUtil.RandomColorString() }, *@
            BorderWidth = 1,
            @* HoverBackgroundColor = ColorUtil.ColorString(0, 0, 0, 0.1),
            HoverBorderColor = "#020202",
            HoverBorderWidth = 1, *@
            @* BorderColor = "#ffffff", *@
            BorderColor = "#020202",
        };

        @* var now = DateTime.Now; *@
        var rndForLine = new Random();
        lineSet.AddRange(Enumerable.Range(2, 4).Select(i => new TimeTuple<double>((Moment)now.AddHours(i), rndForLine.NextDouble() * 4)));
        _config.Data.Datasets.Add(lineSet);
    }
}
```

## 実行結果

実行すると下記のような画面が表示されます。

![Fig_Result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604076/b84cfae6-3877-f423-460a-c7d39972f5d1.png)

# さいごに

現在は諸事情により開発が止まっているChartJs.Blazorですが、
ChartJsもBlazorもとてもいいものなので、
それらをラップするChartJs.Blazorももちろんいいものだと思います。
是非開発が進んでくれることを祈るばかりです。

# 参考URL
[ChartJs.Blazor Samples](https://www.iheartblazor.com/welcome)
[ChartJs.Blazor公式github](https://github.com/mariusmuntean/ChartJs.Blazor)
[ChartJs.Blazorを試してみる](https://qiita.com/KoHey94/items/22fb2ce3b693f6b4242a)