【NGX-Charts】Angularでグラフを作りたい

現在Angulrで作成しているアプリケーション内でグラフを作成したく、`swimlane/ngx-charts`というライブラリを使ってみました。結論、かっこいいグラフが簡単に作れてめっちゃ便利でした・・・

https://zenn.dev/lacolaco/articles/a030e8912a18839d2357


###環境
- Angular：12.0.5
- @swimlane/ngx-charts：20.0.1

###インストール
まずはインストール。

```
npm i @swimlane/ngx-charts --save
```

早速エラー。

```
Error: node_modules/@swimlane/ngx-charts/lib/box-chart/box-chart.component.d.ts:5:40 - error TS7016: Could not find a declaration file for module 'd3-scale'. '/node_modules/d3-scale/dist/d3-scale.js' implicitly has an 'any' type.
  Try `npm i --save-dev @types/d3-scale` if it exists or add a new declaration (.d.ts) file containing `declare module 'd3-scale';`

5 import { ScaleLinear, ScaleBand } from 'd3-scale';
```

ググると

```
npm install @types/d3 --save-dev
```
すると良いよ〜って書いてあるので実行してみるとエラーなくなった！:dolphin:

https://github.com/swimlane/ngx-charts/issues/1686


###モジュール登録

`app.module.ts`に追加します

```typescript:app.module.ts
import { NgxChartsModule } from '@swimlane/ngx-charts';

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    NgxChartsModule,
  ],
)}

```

###実際に使ってみる

ドキュメントはこちら

https://swimlane.gitbook.io/ngx-charts/

デモサイトはこちら

https://swimlane.github.io/ngx-charts/#/ngx-charts/bar-vertical

とりあえず、縦の棒のグラフを作ってみます。StackBlitzからコピペ。

https://stackblitz.com/edit/vertical-bar-chart?embed=1&file=app/app.component.ts



```typescript:app.component.ts
export class AppComponent {
  single: any[] = [
    {
      "name": "Germany",
      "value": 8940000
    },
    {
      "name": "USA",
      "value": 5000000
    },
    {
      "name": "France",
      "value": 7200000
    }
  ];

  view: any[] = [700, 400];

  // options
  showXAxis = true;
  showYAxis = true;
  gradient = false;
  showLegend = true;
  showXAxisLabel = true;
  xAxisLabel = 'Country';
  showYAxisLabel = true;
  yAxisLabel = 'Population';

  colorScheme = {
    domain: ['#5AA454', '#A10A28', '#C7B42C', '#AAAAAA']
  };

  constructor() {
  }

}
```

```html:app.component.html
<ngx-charts-bar-vertical
  [view]="view"
  [scheme]="colorScheme"
  [results]="single"
  [gradient]="gradient"
  [xAxis]="showXAxis"
  [yAxis]="showYAxis"
  [legend]="showLegend"
  [showXAxisLabel]="showXAxisLabel"
  [showYAxisLabel]="showYAxisLabel"
  [xAxisLabel]="xAxisLabel"
  [yAxisLabel]="yAxisLabel"
>
</ngx-charts-bar-vertical>
```

すると型違いによるコンパイルエラーがいくつか。

```
Error: app.component.html:2:4 - error TS2322: Type 'any[]' is not assignable to type '[number, number]'.
  Target requires 2 element(s) but source may have fewer.

2   [view]="view"
```

言われた通りに書き直します。

```typescript:app.component.ts
view: [number, number] = [700, 400];
```

エラー消えました！:dolphin:
`any[]`でも別に間違ってはなくね？（というかデモのコードでそう書かれてるのに）と思いましたが・・・

https://stackoverflow.com/questions/68298395/angular-12-is-not-assignable-to-type-number-number

https://github.com/swimlane/ngx-charts/blob/6a58d9f2d2a2f6f90ad8bc4a1b33087ee65dfeb0/projects/swimlane/ngx-charts/src/lib/common/base-chart.component.ts#L30

ソースコードで`view`はnumberのarray（`number[]`）ではなく2つのnumberの[タプル](https://maku.blog/p/6uzqf4q/)（`[number, number]`）で定義されているからエラーになると・・・へえ〜〜〜


続いてもう一つ出ているエラー。

```
Error: app.component.html:3:4 - error TS2322: Type '{ domain: string[]; }' is not assignable to type 'string | Color'.
  Type '{ domain: string[]; }' is missing the following properties from type 'Color': name, selectable, group

3   [scheme]="colorScheme"
```

とりあえず、`colorScheme`の型を指定してみます。

```typescript:app.component.ts
import { Color } from '@swimlane/ngx-charts'; 

colorScheme: string | Color = {
  domain: ['#5AA454', '#A10A28', '#C7B42C', '#AAAAAA']
};
```

すると、`name`、`selectable`、`group`のプロパティが足りないと・・・

```
Error: app.component.ts:49:3 - error TS2322: Type '{ domain: string[]; }' is not assignable to type 'string | Color'.
  Type '{ domain: string[]; }' is missing the following properties from type 'Color': name, selectable, group

49   colorScheme: string | Color = {
```

`Color`の定義を見てみると、うん。確かに。

```typescript
export interface Color {
    name: string;
    selectable: boolean;
    group: ScaleType;
    domain: string[];
}
```

https://github.com/swimlane/ngx-charts/issues/1673

ググると、Colorはこう定義するべきじゃね？と。

```typescript
export interface Color {
    name?: string;
    selectable?: boolean;
    group?: ScaleType;
    domain: string[];
}
```

言われている通り定義し直したらエラー消えました。:dolphin:
※こういうふうに直接定義し直しちゃって良いのかは正直分からないです・・・


###実際の画面

こんな感じで棒グラフが表示されました！:open_hands:
![スクリーンショット 2022-02-20 21.34.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680199/55eb864f-3b37-55f5-c84d-acf27cfb74eb.png)

試しに2カ国増やしてみます。（ついでに`name`と`value`の`""`をはずしてみたけど特に変化はなかった。）

```typescript:app.component.ts
single: any[] = [
    {
      name: "Germany",
      value: 8940000
    },
    {
      name: "USA",
      value: 5000000
    },
    {
      name: "France",
      value: 7200000
    },
    {
      name: "Japan",
      value: 7200000
    },
    {
      name: "China",
      value: 7200000
    }
  ];
```

![スクリーンショット 2022-02-20 21.39.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680199/876af518-3496-779d-c4a1-01a931f0e4c9.png)

```typescript:app.component.ts
colorScheme: string | Color = {
  domain: ['#5AA454', '#A10A28', '#C7B42C', '#AAAAAA']
};
```
`colorScheme.domein`で指定した色が順に使われるんですね〜

###エラー解決履歴

####Legendをグラフの下に表示させたい
```html:app.component.html
<ngx-charts-bar-vertical
 [legendPosition]="legendPosition" //追加
>
</ngx-charts-bar-vertical>
```

```typescript:app.component.ts
export class AppComponent implements OnInit {

  legendPosition: string = 'below'; //追加

}
```
すると何故かコンパイルエラー。

```
Error: app.component.html:13:4 - error TS2322: Type 'string' is not assignable to type 'LegendPosition'.

13   [legendPosition]="legendPosition"
```

・・・？:thinking:　ググりました

https://github.com/swimlane/ngx-charts/issues/1080

[このコミット](https://github.com/swimlane/ngx-charts/commit/6d591944a7eaa2942b4b4c39c9d3526d28ceb1b9#diff-2b44a01a1e7fa13f98c84eeab10ca35a545d6da4479f57d4b86c9b26cbe08a3a)で`LegendPosition`の(ための)`typing's`が`enum`に変わったと。

https://qiita.com/igm50/items/8c9788d4ba5868642c69

```typescript:app.component.ts
import { LegendPosition } from '@swimlane/ngx-charts';  //追加

export class AppComponent implements OnInit {

  legendPosition: LegendPosition = LegendPosition.Below; //変更

}
```
このように変更してエラー消えました。




###option
https://swimlane.github.io/ngx-charts/#/ngx-charts/bar-vertical

デモサイトをポチポチしてたらどのoptionを変えると何が起きるのかは大体わかるのですが、便利なoptionがあったら追記していきたいと思います！