💽

Highchartsの単位を数値に応じて変更&カスタマイズした単位の位置

2023/06/19に公開

はじめに

ポートでフロントエンドを担当している金髪クァドリンガルの @eicho.chin 🌝です。今回はHighcharts の小技を紹介します。

Highcharts は、JavaScriptライブラリであり、Web上でクライアント側でのグラフ作成を簡単に実現するために使用されます。Highchartsを使用すると、棒グラフ、折れ線グラフ、面グラフなどの様々な種類のグラフを簡単かつ美しく表示することができ、APIも非常に使いやすいです。
公式サイト: https://www.highcharts.com/

今回紹介したいこと

  1. Y軸数値の単位は可変的に実装
    1). +/-(正と負)
    2). 13桁数字 && 兆、億、万
  2. highchartsのY軸の単位を上に表示

今回実装したいグラフ

highcharts

実際は就活会議企業の業績推移グラフに使用されています: https://syukatsu-kaigi.jp/companies/92969

highcharts optionのコード雰囲気

const options = {
    chart: {...}, // chart 全体的な調整
    title: {...},
    tooltip: {
        enabled: false, // tooltip 非表示
    },
    xAxis: {
        categories: // 指定するX軸データ
    },
    yAxis: [ // Arrayも 可能
        {
          // 第一Y軸: 1st yAxis
          id: 'y-axis-unit', // 指定可能
          title:,
          label: {...} // 色々いじれます
          type,
          style: {...} // 提供されている一部のstyleを変更可能
        },
        {
          // 第二Y軸: 2nd yAxis
          id: 'y-axis-second',
         ...
        }
    ],
    // 凡例
    legend: {...},
    series: [...], // データの本体

}

単位を可変に

データのセットなどは省略させていただきます
📃使用するAPI公式ドキュメント: https://api.highcharts.com/highcharts/yAxis.labels.formatter

やることはシンプル🌝です。

1. デフォルトの縦書きの単位をfalseに

yAxisのtitleを '' により上書きを行います。

yAxis-title

...some code
  yAxis: {
    id: "y-axis-jpy",
    title: {
      text: "", // title をなしに設定
    },
    labels: {
      format: "{value}円",
      x: -10,
      type: "logarithmic",
    }

完成形: https://71qrww.csb.app/
コード: https://codesandbox.io/s/highchart-label-first-71qrww

2. 自作formatter 関数

目指す機能2つあります。

  1. +/-(正と負)の対応
  2. 兆、億、万単位の対応

流石に、桁数が長いと、読み解くのも時間がかかります。より分かりやすい単位でディスプレイが可能であれば、読み手も気が楽に閲覧ができます。

label

...some code
yAxis: {
    id: "y-axis-jpy",
    // Primary yAxis
    title: {
      text: "",
    },
    labels: {
      formatter: function () {
        const max = this.axis.max;
        const min = this.axis.min;
        let unit = "";

        if (max >= 1_000_000_000_000 || -min >= 1_000_000_000_000) {
          // 兆
          unit = `<span>(兆円)</span>`;
          return formatValue(this.value, 1_000_000_000_000, unit);
        } else if (max >= 100_000_000 || -min >= 100_000_000) {
          // 億
          unit = `<span>(億円)</span>`;
          return formatValue(this.value, 100_000_000, unit); // 万
        } else if (max >= 10_000 || -min >= 10_000) {
          unit = `<span>(万円)</span>`;
          return formatValue(this.value, 10_000, unit);
        } else {
          return Highcharts.numberFormat(this.value, 0, "", ",");
        }

        function formatValue(value, divider, unit) {
          const formattedValue = `${
            Math.sign(value) === -1 ? "-" : ""
          }${Highcharts.numberFormat(Math.abs(value) / divider, 0, "", ",")}`;

          return `${formattedValue}${unit}`;
        }
      },
      ...

単位の計算は +/- があるため、直接 Highcharts.numberFormat() 使用するのは、難しいです。
なので、max と min と data 数値を比べて、最終的に 符号 + 数値 + 単位 で戻り値として使用します。

完成形: https://hwnvsy.csb.app/
コード: https://codesandbox.io/s/highchart-label-second-hwnvsy

3. maxの上に単位を移動

#2より、追加したポイント

  1. 単位は label の max にのみ、max value の上に表示
  2. 単位の文言部分を dx を使用して位置調整
    label-unit
...some code
labels: {
  formatter: function () {
    const max = this.axis.max;
    const min = this.axis.min;
    const unitDx = 10; // (単位)が左からの平移pixel数値、(単位)と数値がそろえるように
    let unit = "";

    if (max >= 1_000_000_000_000 || -min >= 1_000_000_000_000) {
      unit = `<span dx=${unitDx}>(兆円)</span>`; // dx 調整
      return formatValue(this.value, 1_000_000_000_000, unit);
    } else if (max >= 100_000_000 || -min >= 100_000_000) {
      unit = `<span dx=${unitDx}>(億円)</span>`; // dx 調整
      return formatValue(this.value, 100_000_000, unit);
    } else if (max >= 10_000 || -min >= 10_000) {
      unit = `<span dx=${unitDx}>(万円)</span>`;// dx 調整
      return formatValue(this.value, 10_000, unit);
    } else {
      return Highcharts.numberFormat(this.value, 0, "", ",");
    }

    function formatValue(value, divider, unit) {
      const formattedValue = `${
        Math.sign(value) === -1 ? "-" : ""
      }${Highcharts.numberFormat(Math.abs(value) / divider, 0, "", ",")}`;

      // 最大値の上にのみ(単位)を表示
      return value === max
        ? `${unit}<br>${formattedValue}`
        : formattedValue;
    }

完成形: https://0brjnl.csb.app/
コード: https://codesandbox.io/s/highchart-label-third-0brjnl

最大値の上にのみ(単位)を表示はシンプリなbr を使用していますが、実はdx、dy のline-height の数値に指定しても改行可能なこと試してました。(使用するライブラーによって、svgモードの実際renderによって動作が異なります)

サンプルコード:

<tspan dx="1.2em" dy="1.2em">(億円)</tspan>

最後に

今回はhighcharts ライブラーの実装で実現した小技を紹介しました。
お役に立てれば、幸いです。🦥

Discussion