Highchartsで人口ピラミッドグラフをつくろう

[AutoScale Advent Calendar 2018](https://qiita.com/advent-calendar/2018/auto-scale) 9日目の担当の[matamatak](https://twitter.com/matamatak05)です。
学生インターンとして**Twitterアカウントの統合運用ツール[SocialDog](https://social-dog.net/)**の開発に携わっています。

JSでグラフを描画するときにオススメの**Highchart**について書かせていただきます。
# Highchartsとは

[公式サイト](http://www.highcharts.com/)
JavaScript用のグラフライブラリ
**Free for Non-Commercial**となっており商用利用には注意が必要
Open Sourceなので[Github](https://github.com/highcharts/highcharts)で公開されている

# 人口ピラミッドグラフとは
**世代別の人口と男女比を表すグラフ**
![人口ピラミッドグラフ](https://qiita-image-store.s3.amazonaws.com/0/262657/0f35db1b-6ab7-8478-99a2-1186633b9c37.png)
>[日本の人口統計 - Wikipedia](https://ja.wikipedia.org/wiki/%E6%97%A5%E6%9C%AC%E3%81%AE%E4%BA%BA%E5%8F%A3%E7%B5%B1%E8%A8%88)

一度は目にしたことがあると思います。今回はこちらをHighchartで描画します。

# デモを探す
とりあえず公式のデモから似たようなグラフはないか探したところ
[Bar with negative stack](https://www.highcharts.com/demo/bar-negative-stack)がかなり目指したものと近いようです。

![Bar with negative stack image](https://qiita-image-store.s3.amazonaws.com/0/262657/2a377dac-e15c-6b48-79fc-9621144e2ed9.png)

デモを見る限りソースコードも簡潔なので、すこし修正すれば解決！完！

としたいのですが[画像一枚目](#人口ピラミッドグラフとは)のようにY軸、つまり年代を中央に移動させ共通化させたい。
しかし、ドキュメントを見る限り公式では対応していないらしい。


# なんとかしてみたかった

なんとか表現できないか試行錯誤した結果がこちらです。
![スクリーンショット 2018-11-30 21.54.12.png](https://qiita-image-store.s3.amazonaws.com/0/262657/a2ac9367-cbdb-ee23-a621-0f2c1c88b08a.png)
（コードを簡潔にするために粗い部分もありますが）
一見すると問題ないグラフに仕上がったと思います。


# デモ、ソースコード

### デモ（CodePen）
<p data-height="265" data-theme-id="0" data-slug-hash="BGvrwm" data-default-tab="js,result" data-user="matamatak" data-pen-title="BGvrwm" class="codepen">See the Pen <a href="https://codepen.io/matamatak/pen/BGvrwm/">BGvrwm</a> by matamatak (<a href="https://codepen.io/matamatak">@matamatak</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>


### ソースコード
```HTML:HTML
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="cnt">
  <div id="left"></div>
  <div id="right"></div>
</div>
```

```JavaScript:JS
var categories = [
  '0-4', '5-9', '10-14', '15-19',
  '20-24', '25-29', '30-34', '35-39', '40-44',
  '45-49', '50-54', '55-59', '60-64', '65-69',
  '70-74', '75-79', '80-84', '85-89', '90-94',
  '95-99', '100 + '
];

Highcharts.chart('left', {
  chart: {
    type: 'bar',
    marginRight: 1
  },
  yAxis: {
    min: 0,
    reversed: true,
    title: {
      enabled: false
    }
  },
  xAxis: {
    visible: false,
    reversed: false,
  },
  title: {
    text: ''
  },
  legend: {
    layout: 'vertical',
    align: 'left',
    verticalAlign: 'top',
    x: 30,
    y: 10,
    floating: true,
    backgroundColor: ((Highcharts.theme && Highcharts.theme.legendBackgroundColor) || '#FFFFFF'),
  },
  series: [{
    name: 'man',
    data: [
      2.1, 2.0, 2.1, 2.3, 2.6,
      2.9, 3.2, 3.1, 2.9, 3.4,
      4.3, 4.0, 3.5, 2.9, 2.5,
      2.7, 2.2, 1.1, 0.6, 0.2,
      0.0
    ]
  }]
});

Highcharts.chart('right', {
  chart: {
    type: 'bar'
  },
  yAxis: {
    min: 0,
    enabled: false,
    title: {
      enabled: false
    }
  },
  xAxis: {
    reversed: false,
    categories: categories,
    tickLength: 0
  },
  title: {
    text: ''
  },
  legend: {
    layout: 'vertical',
    align: 'right',
    verticalAlign: 'top',
    x: -20,
    y: 10,
    floating: true,
    backgroundColor: ((Highcharts.theme && Highcharts.theme.legendBackgroundColor) || '#FFFFFF'),
  },
  series: [{
    color: '#ccaadd',
    name: 'woman',
    data: [
      2.1, 2.0, 2.1, 2.3, 2.6,
      2.9, 3.2, 3.1, 2.9, 3.4,
      4.3, 4.0, 3.5, 2.9, 2.5,
      2.7, 2.2, 1.1, 0.6, 0.2,
      0.0
    ]
  },]
});

```

```CSS:CSS
#left,
#right {
  width: 49%;
  display: inline-block;
}

#cnt {
  max-width: 800px;
  margin: 0 auto;
}
```

# 詳細
グラフを**２つ**用意してなんとかしています。試しに片方を非表示にしてみましょう。
legend（凡例）をクリックすると該当のグラフの表示、非表示を切り替えることができます。

![スクリーンショット 2018-11-30 22.16.25.png](https://qiita-image-store.s3.amazonaws.com/0/262657/65668e36-aea5-fca1-a593-74c213a8d73e.png)


# まとめ
ゴリ押しです。保守性も悪いので個人的には使いたくないです。
ただ大抵のグラフは実現できますので、ぜひ一度使ってみてください。