C3.js:独立于图例高度分配图表高度
C3.js: Assigning a chart height independently of the legend height
(抱歉重复发帖,但是 github 上的问题一周后没有得到回复:https://github.com/c3js/c3/issues/2254)
我正在使用 C3 JS,我在同一页面上显示了多个堆叠条形图。每一个都有不同的传说,有些传说比其他的要大得多。由于我只能定义整个图像的高度,图例较大的图表的y轴会变小。
下图说明了这个问题:
我的目标是两个图表上的 y 轴高度相同。图表整体高度(图表+图例)无关紧要。
是否可以为图表指定一个固定高度而不包括此尺寸的图例高度?也许我应该直接使用 D3?
感谢您的关注和这个很棒的库。
最好的,
艾伦
我认为唯一的方法是使用 c3js 示例中的自定义图例(参见 http://c3js.org/samples/legend_custom.html)。
所以你必须禁用图例:
legend: {
show: false
}
并创建您自己的图例(例如使用 d3.js):
function createLegend(chart, container) {
var dataKeys = Object.keys(chart.internal.data.xs);
var names = chart.data.names();
console.log("createLegend", dataKeys, names, chart);
$(container).css("max-height", "none");
$(container).css("width", chart.internal.currentWidth);
d3.select(container).insert('div', '.chart').attr('class', 'legend').selectAll('div')
.data(dataKeys)
.enter().append('div')
.attr('class', 'legend-item')
.attr('data-id', function(id) {
return id;
})
.each(function(id) {
d3.select(this)
.append('span').style('background-color', chart.color(id)).attr('class', 'legend-box');
var text = names[id];
if (!text) text = id;
d3.select(this)
.append('span').html(text).attr('class', 'legend-text');
})
.on('mouseover', function(id) {
chart.focus(id);
})
.on('mouseout', function(id) {
chart.revert();
})
.on('click', function(id) {
$(this).toggleClass("c3-legend-item-hidden")
chart.toggle(id);
$(container).css("max-height", "none");
});
}
var chart1 = c3.generate({
bindto: '#chart1',
size: {
height: 250,
width: 400
},
data: {
x: 'x',
columns: [
['x', 'one', 'two'],
['data1', 30, 200],
['data2', 130, 100],
['data3', 30, 200],
['data4', 130, 100],
['data5', 30, 1200],
['data6', 130, 50],
['data7', 30, 20],
['data8', 130, 100],
['data9', 230, 10]
],
type: 'bar',
names: {
data1: 'Long Name 1',
data2: 'Long Name 2',
data3: 'Long Name 3',
data4: 'Long Name 4',
data5: 'Long Name 5',
data6: 'Long Name 6',
data7: 'Long Name 7',
data8: 'Long Name 8',
data9: 'Long Name 9',
},
groups: [
['data1', 'data2', 'data3', 'data4', 'data5', 'data6', 'data7', 'data8', 'data9']
]
},
axis: {
x: {
type: 'category' // this needed to load string x value
}
},
legend: {
show: false
},
onrendered: function() {
$('#chart1').css("max-height", "none");
}
});
createLegend(chart1, '#chart1');
/* only to highlight chart container */
.chart {
background: lightgray;
border: solid 1px red;
}
.legend-box {
display: inline-block;
margin-left: 7px;
margin-right: 7px;
padding: 5px;
}
.legend-item {
cursor: pointer;
display: inline-block;
}
.legend-text {
font-family: "Helvetica";
font-size:12px;
white-space: nowrap;
}
.legend {
width: 100%;
display: inline-block;
text-align: center;
overflow: hidden;
}
<script src="https://code.jquery.com/jquery-3.1.0.min.js" type="text/javascript"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.18/c3.css" rel="stylesheet" type="text/css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.18/c3.min.js" type="text/javascript"></script>
<div id="chart1" class="chart"></div>
这是一个显示完整示例的 jsfiddle:https://jsfiddle.net/beaver71/zp7km2L1/
可能有点晚了,但当前版本的 C3 还没有这样的功能。
您可以通过javascript中的下一种方式完成:
- 一如既往地设置和配置您的图表和图例(高度将包括图例高度,没关系)。
- 获取所有图表的高度(不带图例):originalHeightChart.
- 隐藏图例。重要!:隐藏完成后进行下一步,否则会错误地获取下一个高度,如示例。
- 再次获取所有图表的高度:totalHeightChart。现在图例高度是当前高度减去之前的高度:totalHeightChart-originalHeightChart
- 计算新高度:totalHeightChart + ( totalHeightChart - originalHeightChart).
- 使用新高度调整图表大小。
- 显示图例。
完成!
现在 javascript 代码示例:
var yourChartObject = c3.generate( yourJSonDataOrAnyWay );
var width = jQuery('#yourIdChart').find(".c3-chart").get(0).getBBox().width; //to get g group of svg chart
var partialHeight = jQuery('#yourIdChart').find(".c3-chart").get(0).getBBox().height; //to get g group of svg chart
yourChartObject.legend.hide();
var totalHeight = jQuery('#yourIdChart').find(".c3-chart").get(0).getBBox().height; //to get g group of svg chart
var newHeight = totalHeight + (totalHeight - partialHeight);
setTimeout(() => {
yourChartObject.resize({ 'height': newHeight, 'width': width });
yourChartObject.legend.show();
},100);
(抱歉重复发帖,但是 github 上的问题一周后没有得到回复:https://github.com/c3js/c3/issues/2254)
我正在使用 C3 JS,我在同一页面上显示了多个堆叠条形图。每一个都有不同的传说,有些传说比其他的要大得多。由于我只能定义整个图像的高度,图例较大的图表的y轴会变小。
下图说明了这个问题:
我的目标是两个图表上的 y 轴高度相同。图表整体高度(图表+图例)无关紧要。
是否可以为图表指定一个固定高度而不包括此尺寸的图例高度?也许我应该直接使用 D3?
感谢您的关注和这个很棒的库。
最好的, 艾伦
我认为唯一的方法是使用 c3js 示例中的自定义图例(参见 http://c3js.org/samples/legend_custom.html)。
所以你必须禁用图例:
legend: {
show: false
}
并创建您自己的图例(例如使用 d3.js):
function createLegend(chart, container) {
var dataKeys = Object.keys(chart.internal.data.xs);
var names = chart.data.names();
console.log("createLegend", dataKeys, names, chart);
$(container).css("max-height", "none");
$(container).css("width", chart.internal.currentWidth);
d3.select(container).insert('div', '.chart').attr('class', 'legend').selectAll('div')
.data(dataKeys)
.enter().append('div')
.attr('class', 'legend-item')
.attr('data-id', function(id) {
return id;
})
.each(function(id) {
d3.select(this)
.append('span').style('background-color', chart.color(id)).attr('class', 'legend-box');
var text = names[id];
if (!text) text = id;
d3.select(this)
.append('span').html(text).attr('class', 'legend-text');
})
.on('mouseover', function(id) {
chart.focus(id);
})
.on('mouseout', function(id) {
chart.revert();
})
.on('click', function(id) {
$(this).toggleClass("c3-legend-item-hidden")
chart.toggle(id);
$(container).css("max-height", "none");
});
}
var chart1 = c3.generate({
bindto: '#chart1',
size: {
height: 250,
width: 400
},
data: {
x: 'x',
columns: [
['x', 'one', 'two'],
['data1', 30, 200],
['data2', 130, 100],
['data3', 30, 200],
['data4', 130, 100],
['data5', 30, 1200],
['data6', 130, 50],
['data7', 30, 20],
['data8', 130, 100],
['data9', 230, 10]
],
type: 'bar',
names: {
data1: 'Long Name 1',
data2: 'Long Name 2',
data3: 'Long Name 3',
data4: 'Long Name 4',
data5: 'Long Name 5',
data6: 'Long Name 6',
data7: 'Long Name 7',
data8: 'Long Name 8',
data9: 'Long Name 9',
},
groups: [
['data1', 'data2', 'data3', 'data4', 'data5', 'data6', 'data7', 'data8', 'data9']
]
},
axis: {
x: {
type: 'category' // this needed to load string x value
}
},
legend: {
show: false
},
onrendered: function() {
$('#chart1').css("max-height", "none");
}
});
createLegend(chart1, '#chart1');
/* only to highlight chart container */
.chart {
background: lightgray;
border: solid 1px red;
}
.legend-box {
display: inline-block;
margin-left: 7px;
margin-right: 7px;
padding: 5px;
}
.legend-item {
cursor: pointer;
display: inline-block;
}
.legend-text {
font-family: "Helvetica";
font-size:12px;
white-space: nowrap;
}
.legend {
width: 100%;
display: inline-block;
text-align: center;
overflow: hidden;
}
<script src="https://code.jquery.com/jquery-3.1.0.min.js" type="text/javascript"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.18/c3.css" rel="stylesheet" type="text/css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.18/c3.min.js" type="text/javascript"></script>
<div id="chart1" class="chart"></div>
这是一个显示完整示例的 jsfiddle:https://jsfiddle.net/beaver71/zp7km2L1/
可能有点晚了,但当前版本的 C3 还没有这样的功能。
您可以通过javascript中的下一种方式完成:
- 一如既往地设置和配置您的图表和图例(高度将包括图例高度,没关系)。
- 获取所有图表的高度(不带图例):originalHeightChart.
- 隐藏图例。重要!:隐藏完成后进行下一步,否则会错误地获取下一个高度,如示例。
- 再次获取所有图表的高度:totalHeightChart。现在图例高度是当前高度减去之前的高度:totalHeightChart-originalHeightChart
- 计算新高度:totalHeightChart + ( totalHeightChart - originalHeightChart).
- 使用新高度调整图表大小。
- 显示图例。
完成!
现在 javascript 代码示例:
var yourChartObject = c3.generate( yourJSonDataOrAnyWay );
var width = jQuery('#yourIdChart').find(".c3-chart").get(0).getBBox().width; //to get g group of svg chart
var partialHeight = jQuery('#yourIdChart').find(".c3-chart").get(0).getBBox().height; //to get g group of svg chart
yourChartObject.legend.hide();
var totalHeight = jQuery('#yourIdChart').find(".c3-chart").get(0).getBBox().height; //to get g group of svg chart
var newHeight = totalHeight + (totalHeight - partialHeight);
setTimeout(() => {
yourChartObject.resize({ 'height': newHeight, 'width': width });
yourChartObject.legend.show();
},100);