【Highcharts】折れ線グラフのハマりPoints

Highcharts

Javascriptの高機能なグラフ描画ライブラリHighchartsを利用する際に折れ線グラフでハマったことを戒めとしてメモしておきます。

Highcharts - Interactive Charting Library for Developers
Create interactive data visualization for web and mobile projects with Highcharts core, Highcharts Stock, Highcharts Map...

やっちまったリスト(ハマりPoints)

  • datetimeで秒単位のUNIX Timestampを使ってしまう
  • timezoneを設定せず日付がずれていると悩んでしまう
  • timezoneを設定したのにformatterで別のHighchartsで処理した結果を返してしまい日付がずれていると悩んでしまう
  • X軸上(y=0)にアノテーションを表示するようにしたのにY軸のminを設定せずに表示されないと悩んでしまう

datetimeで秒単位のUNIX Timestampを使ってしまう

Highchartsのdatetime形式で扱う時間の単位はミリ秒(1000分の1秒)単位のUNIX Timestampです。

筆者はバックエンドのPHPのDateTimeオブジェクトからgetTimestamp()メソッドで受け取った値をそのまま差し込んでしまい、ハマりました。。

例えば、2025年1月~2025年5月の月次売上を折れ線グラフにしようとして

X軸のtypeをdatetimeに設定し

                xAxis: {
                    type: "datetime",
                    title: {
                        text: "販売月"
                    },
                    labels: {
                        formatter () {
                            const date = new Date(this.value);
                            return date.toLocaleDateString('ja-JP', { 
                                year: 'numeric', 
                                month: 'short' 
                            });
                        }
                    }
                },

次のようにデータを差し込むと、

                series: [
                    {
                        name: "商品A",
                        color: "#7fbfff",
                        data: [
                            [1735657200, 1825],
                            [1738335600, 2235],
                            [1740754800, 1765],
                            [1743433200, 2156],
                            [1746025200, 2488],
                            [1748703600, 2847],
                        ]
                    }, {
                        name: "商品B",
                        color: "#ff7f7f",
                        data: [
                            [1735657200, 1466],
                            [1738335600, 1159],
                            [1740754800, 1573],
                            [1743433200, 3185],
                            [1746025200, 3564],
                            [1748703600, 4285],
                        ]
                    }, {
                        name: "商品C",
                        color: "#7fffff",
                        data: [
                            [1735657200, 4411],
                            [1738335600, 3467],
                            [1740754800, 1234],
                            [1743433200, 564],
                            [1746025200, 0],
                            [1748703600, 0],
                        ]
                    },
                ],

こんなグラフが出来上がります。

全ての販売月が1970年1月・・・

PHPのDateTimeオブジェクトのgetTimestamp()は秒単位なので1000倍してから使いましょう。

                series: [
                    {
                        name: "商品A",
                        color: "#7fbfff",
                        data: [
                            [1735657200000, 1825],
                            [1738335600000, 2235],
                            [1740754800000, 1765],
                            [1743433200000, 2156],
                            [1746025200000, 2488],
                            [1748703600000, 2847],
                        ]
                    }, {
                        name: "商品B",
                        color: "#ff7f7f",
                        data: [
                            [1735657200000, 1466],
                            [1738335600000, 1159],
                            [1740754800000, 1573],
                            [1743433200000, 3185],
                            [1746025200000, 3564],
                            [1748703600000, 4285],
                        ]
                    }, {
                        name: "商品C",
                        color: "#7fffff",
                        data: [
                            [1735657200000, 4411],
                            [1738335600000, 3467],
                            [1740754800000, 1234],
                            [1743433200000, 564],
                            [1746025200000, 0],
                            [1748703600000, 0],
                        ]
                    },
                ],

これで次のように表示されます。

timezoneを設定せず日付がずれていると悩んでしまう

HighchartsのデフォルトタイムゾーンはUTCです。

日本時間はUTCに対して9時間進んでおり、

UTCは日本時間に対して9時間遅れていることになっています。

例えば、UNIX Timestamp「1748703600000」は、

日本時間「2025年6月1日0時0分0.000000秒」のつもりで取得したものですが、

UTCで扱って書式出力すると、日本時間の9時間前、

つまり「2025年5月31日15時0分0.000000秒」となってしまいます。

                series: [
                    {
                        name: "商品A",
                        color: "#7fbfff",
                        data: [
                            [1735657200000, 1825],  // 日本時間2025年1月1日0時0分0.0000000秒
                            [1738335600000, 2235],  // 日本時間2025年2月1日0時0分0.0000000秒
                            [1740754800000, 1765],  // 日本時間2025年3月1日0時0分0.0000000秒
                            [1743433200000, 2156],  // 日本時間2025年4月1日0時0分0.0000000秒
                            [1746025200000, 2488],  // 日本時間2025年5月1日0時0分0.0000000秒
                            [1748703600000, 2847],  // 日本時間2025年6月1日0時0分0.0000000秒
                        ]
                    }, {
                        name: "商品B",
                        color: "#ff7f7f",
                        data: [
                    ・・・(中略)・・・
                    },
                ],

timezoneの設定無しに出力すると・・・

2025年6月1日0時0分0.000000秒のつもりが、

マーカーにマウスホバーすると9時間前の

「5月31日土曜日 15:00」となっているではありませんか。。

Highchartsオプションのトップレベルのプロパティtimeの子要素として、

「useUTC: false」と「timezone: ‘Asia/Tokyo’」の設定をしておきましょう。

            var chart = Highcharts.chart("trend-line-chart-container", {

                title: {
                    text: "",
                    align: "left"
                },

                time: {
                    useUTC: false,
                    timezone: 'Asia/Tokyo',
                },

これで表示すれば

tooltipが「2025年6月」として表示されました。

timezoneを設定したのにformatterで別のHighchartsで処理した結果を返してしまい日付がずれていると悩んでしまう

X軸の日付ラベルをカスタム書式にしようと、xAxisのformatterで

別のHighcharts.date_format()をreturnしてしまうと

せっかく設定したtimezoneが適用されずUTCの処理結果が返されてしまいます。

                xAxis: {
                    type: "datetime",
                    title: {
                        text: "販売月"
                    },
                    labels: {
                        formatter () {
                            return Highcharts.dateFormat('%Y年%m月', this.value);
                        }
                    }
                },

これで表示すると

2025年1月~2025年6月の表示にするつもりが

2024年12月~2025年5月の表示になってしまいます。。

▼問題は2点:

1.timezoneのような共通設定を個別インスタンスで設定している

2.個別インスタンスにtimezoneを施した状態で別クラスはいかん

▼対処方法2通り:

1.timezoneのような共通設定はsetOptions()で事前にやっておけ。

 ⇒そうしたら別クラスも問題なし。

            Highcharts.setOptions({
                time: {useUTC: false, timezone: 'Asia/Tokyo'}
            });
            var chart = Highcharts.chart("trend-line-chart-container", {
            ・・・(以下略)・・・

2.formatter側でJavascriptのDateオブジェクトのtoLocaleDateString()で’ja-JP’指定で書式変換

 ⇒ timezone設定関係なし

                xAxis: {
                    type: "datetime",
                    title: {
                        text: "販売月"
                    },
                    labels: {
                        formatter () {
                            return (new Date(this.value)).toLocaleDateString('ja-JP', { 
                                year: 'numeric', 
                                month: 'short' 
                            });
                        }
                    }
                },

上記1でも2でも同じ結果になります。

対処としては、共通設定を事前にsetOptions()しておく方がベター&スマートでしょう。

X軸上(y=0)にアノテーションを表示するようにしたのにY軸のminを設定せずに表示されないと悩んでしまう

X軸上にアノテーションを表示するように設定し

                annotations: [{
                    visible: true,
                    crop: false,
                    labelOptions: {
                        borderColor: "#0000ff",
                        backgroundColor: "#ffffdd",
                        verticalAlign: "top",
                        style: {
                            fontSize: "10px",
                        },
                        y: 15
                    },
                    labels: [
                        {
                            point: {
                                xAxis: 0,
                                yAxis: 0,
                                x: 1736208000000, // 2025年1月7日
                                y: 0
                            },
                            text: "LA山火事",
                        },
                        {
                            point: {
                                xAxis: 0,
                                yAxis: 0,
                                x: 1739318400000, // 2025年2月12日
                                y: 0
                            },
                            text: "米露首脳会談",
                        },
                ・・・(中略)・・・
                }],

次のようなデータを差し込んで

                yAxis: [
                    {
                    title: {
                        text: "売上金額(円)"
                    },
                }],

                series: [
                    {
                        name: "商品A",
                        color: "#7fbfff",
                        data: [
                            [1735657200000, 5825],
                            [1738335600000, 6235],
                            [1740754800000, 5765],
                            [1743433200000, 6156],
                            [1746025200000, 6488],
                            [1748703600000, 6847],
                        ]
                    }, {
                        name: "商品B",
                        color: "#ff7f7f",
                        data: [
                            [1735657200000, 5466],
                            [1738335600000, 5159],
                            [1740754800000, 5573],
                            [1743433200000, 7185],
                            [1746025200000, 7564],
                            [1748703600000, 8285],
                        ]
                    },
                ],

グラフを表示してみると・・・

Y軸の表示範囲が4k~10kになってしまい、

Y=0に設置したアノテーションが表示されません。

Y軸のminを設定し、アノテーションのYの値と同じにしておく必要があります。

                yAxis: [
                    {
                    title: {
                        text: "売上金額(円)"
                    },
                    min: 0
                }],

こうすることでY=0に配置したアノテーションが表示されます。

以上、折れ線グラフにおけるハマりPointsでした。

  • 0
  • 0
  • 0
  • 0

コメント

タイトルとURLをコピーしました