JavaScript
c3.js

tooltipに値の合算値を出したい

More than 1 year has passed since last update.

始まり

tooltip(グラフにオンマウスした時に表示されるやつ)に表示してあるグラフの合算値を出したい。
上記を実現する時、皆さんはどうしますか?
私はtooltipをカスタマイズして表示する方法へ行きつきました。

調べてみよう

そもそもカスタムできるのかなと思って公式サイトのリファレンスを確認したところ、
tooltip.contentsという項目に答えが書いてありました。
Set custom HTML for the tooltip.つまりHTMLを書けと。

リファレンスでは以下の様な形式で定義しろと記載していますが、情報が少なすぎて引数が何をしているか謎です。

tooltip: {
  contents: function (d, defaultTitleFormat, defaultValueFormat, color) {
    return ... // formatted html as you want
  }
}

見てみよう

なので、ソースコードを確認してデフォルトの状態を参考にします。

c3_chart_internal_fn.getTooltipContent = function (d, defaultTitleFormat, defaultValueFormat, color) {
    var $$ = this, config = $$.config,
        titleFormat = config.tooltip_format_title || defaultTitleFormat,
        nameFormat = config.tooltip_format_name || function (name) { return name; },
        valueFormat = config.tooltip_format_value || defaultValueFormat,
        text, i, title, value, name, bgcolor;
    for (i = 0; i < d.length; i++) {
        if (! (d[i] && (d[i].value || d[i].value === 0))) { continue; }

        if (! text) {
            title = titleFormat ? titleFormat(d[i].x) : d[i].x;
            text = "<table class='" + CLASS.tooltip + "'>" + (title || title === 0 ? "<tr><th colspan='2'>" + title + "</th></tr>" : "");
        }

        value = valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index);
        if (value !== undefined) {
            name = nameFormat(d[i].name, d[i].ratio, d[i].id, d[i].index);
            bgcolor = $$.levelColor ? $$.levelColor(d[i].value) : color(d[i].id);

            text += "<tr class='" + CLASS.tooltipName + "-" + d[i].id + "'>";
            text += "<td class='name'><span style='background-color:" + bgcolor + "'></span>" + name + "</td>";
            text += "<td class='value'>" + value + "</td>";
            text += "</tr>";
        }
    }
    return text + "</table>";
};

書いてみよう

デフォルトのままコピペだと、変数の定義がなかったりでエラーになるので、不要なコードを削ります。
そして合計値を出す処理を追加します。

tooltip: {
    // tooltipの表示のカスタマイズ
    contents: function (d, defaultTitleFormat, defaultValueFormat, color) {
        var $$ = this,
            titleFormat = defaultTitleFormat,
            nameFormat = function (name) {
                    return name;
                },
            valueFormat = defaultValueFormat,
            total = 0,
            text, i, title, value, name, bgcolor;
        for (i = 0; i < d.length; i++) {
            if (!(d[i] && (d[i].value || d[i].value === 0))) {
                continue;
            }
            if (!text) {
                title = titleFormat ? titleFormat(d[i].x) : d[i].x;
                text = "<table class='c3-tooltip c3-tooltip-container'>" + (title || title === 0 ? "<tr><th colspan='2'>" + title + "</th></tr>" : "");
            }
            name = nameFormat(d[i].name, d[i].ratio, d[i].id, d[i].index);
            value = valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index);
            bgcolor = $$.levelColor ? $$.levelColor(d[i].value) : color(d[i].id);
            total += parseInt(value.split(",").join(""));
            text += "<tr class='" + d[i].id + "'>";
            text += "<td class='name'><span style='background-color:" + bgcolor + "'></span>" + name + "</td>";
            text += "<td class='value'>" + value.toLocaleString() + "</td>";
            text += "</tr>";
        }
        text += "<tr><td class='name'>合計値</td>";
        return text + "<td class='total'>" + total.toLocaleString() + "</td></tr></table>";
    }
}

ちなみにこれだけだと、そもそもtooltipが出なくなります。
y軸のフォーマット指定しなければいけません。

    axis : {
        y : {
            tick: {
                format: d3.format("d")
            }
        }
    },

出来ました

まだ不要なコードが残っているような気がしますが、これでtooltipで合計値が出る様になりました。