C3.js - 堆积条形图 - 我可以使值包含而不是相互堆叠吗?

时间:2017-01-31 10:09:22

标签: javascript c3.js

我使用C3.js库创建堆积条形图(我当前的代码位于底部的jsfiddle中)。问题是默认情况下列是...堆叠的。由于我需要创建具有最小值,平均值和最大值的列,因此我希望这些值相互包含,而不是堆栈。例如。如果我有min = 10,平均值= 50且max = 100,我希望条形高度为100,而不是160.是否有任何内置方式来支持这种行为?

我目前的代码:

<div id="chart"></div>

<script>
    var chart = c3.generate({
        bindTo: '#chart',
        data: {
            columns: [
                ['min', 10, 25, 15],
                ['avg', 50, 33, 51],
                ['max', 100, 75, 200]
            ],
            type: 'bar',
            groups: [
                ['min', 'avg', 'max']
            ]
        }
    });
</script>

这是我的代码的jsfiddle: https://jsfiddle.net/gguej6n0/

3 个答案:

答案 0 :(得分:2)

是的,我将此添加为另一个答案,因为它完全不同,如果我改变原来的答案,那么评论就没有意义了。

这一次,我利用了c3中发现的错误...功能(错误?),导致其他用户无意中获得了您想要的效果。

c3.js generate a stacked bar from JSON payload

基本上,如果您将数据作为json提供,如果您将每个数据作为一个单独的点提供,您可以获得所需的效果 例如这样做会在同一列上超过最小值和最大值,即使它们是要堆叠的

        [{ "x-axis": "0",
            "min": 30
        },
        { "x-axis": "0",
            "max": 40
        }],

然而,这种方式将叠加它们:

        [{ "x-axis": "0",
            "min": 30,
            "max": 40
        }],

所以我们需要的是将原始的基于列的数据转换为json对象的例程,其中每个数据都是单独分配的:

http://jsfiddle.net/gvn3y0q6/5/

var data = [
                ['min', 10, 25, 15, 12],
                ['avg', 50, 33, 51, 24],
                ['max', 100, 75, 200, 76]
            ];

var json = [];
data.forEach (function (datum) {
    var series = datum[0];
    for (var i = 1; i < datum.length; i++) {
    var jdatum = {"x-axis": i-1};
    jdatum[series] = datum[i];
    json.push (jdatum);
  }
});

var chart = c3.generate({
    data: {
        x: "x-axis",
        json:json,
        keys: {
           x: "x-axis",
           value: ["max", "avg", "min"]
        },
        groups: [
           ['max', 'avg', 'min']
        ],
        type: 'bar',
    },
     bar: {
        width: {
            ratio: 0.95
        }
     },
     axis: {
       x: {
         padding: {
           left: 0.5,
           right: 0.5,
         }
       }
     },
     tooltip: {
         grouped: true,
         contents: function (d, defaultTitleFormat, defaultValueFormat, color) {
             var data = this.api.data.shown().map (function(series) {
                var matchArr = series.values.filter (function (datum) {
                    return datum.value != undefined && datum.x === d[0].x;
                });
                matchArr[0].name = series.id;
                return matchArr[0];
             });

            return this.getTooltipContent(data, defaultTitleFormat, defaultValueFormat, color);
      }
     }
    });

这一次,隐藏一个系列并不影响其他系列。仍然需要一些工具提示jiggery-pokery,否则我们只会在悬停在其中一个堆栈上时获得工具提示中报告的值之一。看起来这些数据包含很多空值点,这让我觉得这是一种我在这里利用的错误。

所以请记住,这可能会在未来的某个时刻得到解决(或者如果有人指出这对于做这种情节有用的话可能会留下来) - 那么这似乎就是你想做的事情< / p>

答案 1 :(得分:0)

我并不知道任何内置的内容可以使这些条形图如你所描述的那样相互融合,但是并列视图可以帮助吗?如果是,请删除分组。

请参阅https://jsfiddle.net/gguej6n0/1/

var chart = c3.generate({
    bindTo: '#chart',
    data: {
        columns: [
            ['min', 10, 25, 15],
            ['avg', 50, 33, 51],
            ['max', 100, 75, 200]
        ],
        type: 'bar'
    },
    bar: {
            width: {
                ratio: 0.3
        }
    }
});

答案 2 :(得分:0)

我不认为c3有'overplot'栏选项,但你可以按摩你的数据......

基本上预先处理数据,因此max实际上是max-avg,而avg实际上是avg-min

然后工具提示例程恢复正确的总计以显示给用户

如果您将数据传递到其他任何内容并记住数据已更改并恢复(或保留副本),请务必小心

https://jsfiddle.net/gguej6n0/5/

var data = [
            ['min', 10, 25, 15],
            ['avg', 50, 33, 51],
            ['max', 100, 75, 200]
        ];

    for (var n = data.length-1; n > 0; n--) {
    for (var m = 1; m < data[n].length; m++) {
    data[n][m] -= data[n-1][m];
  }
}


var chart = c3.generate({
      bindTo: '#chart',
    data: {
        columns: data,
        type: 'bar',
        groups: [
            ['min', 'avg', 'max']
        ]
    },
    tooltip: {
      contents: function (d, defaultTitleFormat, defaultValueFormat, color) {
                var dc = d.map (function (dd) {
                    return {value: dd.value, x: dd.x, id: dd.id, name: dd.name, index: dd.index};
            })
                for (var n= 1; n < dc.length; n++) {
                    dc[n].value += dc[n-1].value;
            }
            return this.getTooltipContent(dc, defaultTitleFormat, defaultValueFormat, color);
      }
  }
});