我正在尝试根据具有该x值的非零堆栈的数量动态设置每个x点的宽度。
示例:
我想通过减小每个日期的宽度来消除空白。 (9月7日的宽度应为2,9月8日和9月9日的宽度应为1,而不是所有3个日期的宽度都为3)
这是一个更极端的例子,浪费了很多空间:
我研究了各种图表,但似乎找不到包含堆叠和分组的各种图表的示例。 我在stackoverflow上找到的最接近的问题是Display Different Number of Groups in Highcharts Stacked Column Graph,但该答案不会改变点的宽度,只是使条居中。
JSFiddle:http://jsfiddle.net/t3z76o4b/3/
$(function() {
$('#container').highcharts({
chart: {
type: 'column',
},
legend: {
enabled: false
},
title: {
text: 'Fruits by day'
},
xAxis: {
type: 'category',
labels: {
rotation: -45,
formatter: function() {
var placeholder = Number(this.value);
if (!!placeholder) {
return ""
}
//var obj = data[this.value];
if (this.axis.series[0].levelNumber == 1 && !this.isFirst) {
return '';
} else {
return this.value;
}
}
},
crosshair: true,
},
plotOptions: {
series: {
stacking: 'normal'
}
},
series: [{
name: "Apples",
stack: "Apples",
date: "7 Sep 2018",
data: [{
color: "rgba(51,193,59,1)",
name: "7 Sep 2018",
y: 1
},
{
color: "rgba(51,193,50,0.4)",
name: "7 Sep 2018",
y: 2
}],
},
{
name: "Blueberries",
stack: "Blueberries",
date: "7 Sep 2018",
data: [{
color: "rgba(51,50,250,1)",
name: "7 Sep 2018",
y: 3
},
{
color: "rgba(51,50,250,0.4)",
name: "7 Sep 2018",
y: 1
}],
},
{
name: "Oranges",
stack: "Oranges",
date: "8 Sep 2018",
data: [{
color: "rgba(250,193,10,0.5)",
name: "8 Sep 2018",
y: 1
}, ],
},
{
name: "Blueberries",
stack: "Blueberries",
date: "9 Sep 2018",
data: [{
color: "rgba(51,50,250,1)",
name: "9 Sep 2018",
y: 2
}],
},
]
});
});
在上面的JSFiddle中,每个系列元素代表特定日期的特定水果:
谢谢!
答案 0 :(得分:1)
不幸的是,Highcharts将组空间计算为xAxis宽度除以类别长度。因此,各个类别之间的空间将始终相等。如上所示,该图表需要对Highcharts核心功能进行很多更改,并且很难实现。
只有一些自定义代码才能完成组中居中的列
var stacks = [
'section 1',
'section 2',
'section 3',
'section 4',
'section 5',
'section 6',
'section 7'
];
var categoriesStacksColl = [];
var seriesStackColl = {};
function calculateColumnTranslate(params) {
var m = params.stackLen / 2 + 0.5, // middle bar + offset to calc
barIndex = params.stackIndex,
a = Math.abs(barIndex - m), // bar offset from the middle point
barW = params.barW,
p = params.padding,
posX,
translateX;
if (barIndex === m) {
posX = -barW / 2;
} else if (barIndex > m) {
posX = a * barW + a * p - barW / 2;
} else {
posX = -a * barW - a * p - barW / 2;
}
translateX = posX - params.offset;
return translateX;
}
// Inside Highcharts options
chart: {
type: 'column',
events: {
load: function() {
var chart = this,
series = chart.series,
categoriesLen = chart.xAxis[0].tickPositions.length,
changeWidthFlag = false,
seriesPoints,
nextSeriesPoints,
stack,
length,
arrIndex,
i,
j;
categoriesStacksColl = [];
// Init stacks per categories array
for (j = 0; j < categoriesLen; j++) {
categoriesStacksColl.push(stacks.slice());
}
series.forEach(function(singleSeries) {
stack = singleSeries.options.stack;
if (!seriesStackColl[stack]) {
seriesStackColl[stack] = [];
}
seriesStackColl[stack].push(singleSeries);
});
stacks.forEach(function(initStack) {
seriesPoints = seriesStackColl[initStack][0].points;
length = seriesStackColl[initStack].length;
seriesPoints.forEach(function(point, index) {
if (!point.y && length === 1) {
// increase column width
changeWidthFlag = true;
} else if (!point.y && length > 1) {
changeWidthFlag = true;
for (i = 1; i < length; i++) {
nextSeriesPoints = seriesStackColl[initStack][i].points;
if (nextSeriesPoints[index].y) {
changeWidthFlag = false;
}
}
}
// when all points in category stack are null
if (changeWidthFlag) {
arrIndex = categoriesStacksColl[index].indexOf(initStack);
categoriesStacksColl[index].splice(arrIndex, 1);
changeWidthFlag = false;
}
});
});
},
render: function() {
var chart = this,
series = chart.series[0],
columnMetrics = series.columnMetrics,
barW = columnMetrics.width,
barOffsets = {},
offsets = [],
columnsToTranslate = [],
offsetMin = 0,
offsetMax = 0,
columnsGroupLen = stacks.length,
offset,
columnsGroupWidth,
padding,
point,
pointOffset,
stackIndex,
stackLen,
pointOffsetTemp,
translateBarX;
stacks.forEach(function(stack) {
if (seriesStackColl[stack][0].visible) {
offset = seriesStackColl[stack][0].columnMetrics.offset;
offsetMax = offsetMax < offset ? offset : offsetMax;
offsetMin = offsetMin > offset ? offset : offsetMin;
barOffsets[stack] = offset;
offsets.push(offset);
}
});
columnsGroupWidth = Math.abs(offsetMin) + Math.abs(offsetMax) + barW;
padding = (columnsGroupWidth - columnsGroupLen * barW) / (columnsGroupLen - 1);
categoriesStacksColl.forEach(function(cat, index) {
if (cat.length < stacks.length) {
columnsToTranslate.push({
index: index,
stack: cat
});
}
});
columnsToTranslate.forEach(function(elem) {
stackIndex = 0;
pointOffsetTemp = 0;
chart.series.forEach(function(singleSeries) {
point = singleSeries.points[elem.index];
if (point.y && singleSeries.visible) {
pointOffset = point.series.columnMetrics.offset;
stackLen = elem.stack.length;
if (pointOffsetTemp !== pointOffset) {
pointOffsetTemp = pointOffset;
stackIndex++;
}
translateBarX = calculateColumnTranslate({
padding: padding,
barW: barW,
offset: pointOffset,
stackIndex: stackIndex,
stackLen: stackLen
});
point.graphic.translate(translateBarX);
}
});
});
}
}
}