我已经看过很多关于这个主题的帖子,但似乎这个问题没有得到妥善解决。
我们有大约30分的大分散(没有压倒性的)。但在某些情况下,这些点会非常接近或重叠(我猜我们真的不能做到这一点)。
主要问题是我们希望数据标签始终可见,并且当这些数据标签彼此接近时,这些数据标签会重叠。
我们尝试过 allowOverlap:false ,但这并不是我们需要/想要的。我们理想的结果是允许所有数据标签显示在散布内的屏幕上,同时仍然能够随时读取每个数据标签。
我们是通过调整点的分离还是通过调整数据标签的分离/填充来解决这个问题?有什么建议?谢谢。
答案 0 :(得分:2)
我还没有从Highcharts找到这个问题的工作配置解决方案(虽然我不能保证最新版本中没有一个)。但是,有一些算法可以对分割数据标签的标签坐标进行可接受的随机化。
以下是一些可以帮助您使用算法的有用链接:
wordcloud package in R(cloud.R是包含算法的文件)
R代码的JavaScript中的一些伪伪代码转换将是:
splitLabels: function() {
// Create an array of x-es and y-es that indicate where your data lie
var xArr = getAllDataX();
var yArr = getAllDataY();
var labelsInfo = {};
this.chartSeries.forEach(function(el) {
var text = el.data.name;
labelsInfo[el.data.id] = {
height: getHeight(text),
width: getWidth(text),
text: text
};
}, this);
var sdx = getStandardDeviation(xArr);
var sdy = getStandardDeviation(yArr);
if(sdx === 0) sdx = 1;
if(sdy === 0) sdy = 1;
var boxes = [];
var xlim = [], ylim = [];
xlim[0] = this.chart.xAxis[0].getExtremes().min;
xlim[1] = this.chart.xAxis[0].getExtremes().max;
ylim[0] = this.chart.yAxis[0].getExtremes().min;
ylim[1] = this.chart.yAxis[0].getExtremes().max;
for (var i = 0; i < data.length; i++) {
var pointX = data[i].x;
var pointY = data[i].y;
if (pointX<xlim[0] || pointY<ylim[0] || pointX>xlim[1] || pointY>ylim[1]) continue;
var theta = Math.random() * 2 * Math.PI,
x1 = data[i].x,
x0 = data[i].x,
y1 = data[i].y,
y0 = data[i].y,
width = labelsInfo[data[i].id].width,
height = labelsInfo[data[i].id].height ,
tstep = Math.abs(xlim[1] - xlim[0]) > Math.abs(ylim[1] - ylim[0]) ? Math.abs(ylim[1] - ylim[0]) / 100 : Math.abs(xlim[1] - xlim[0]) / 100,
rstep = Math.abs(xlim[1] - xlim[0]) > Math.abs(ylim[1] - ylim[0]) ? Math.abs(ylim[1] - ylim[0]) / 100 : Math.abs(xlim[1] - xlim[0]) / 100,
r = 0;
var isOverlapped = true;
while(isOverlapped) {
if((!hasOverlapped(x1-0.5*width, y1-0.5*height, width, height, boxes)
&& x1-0.5*width>xlim[0] && y1-0.5*height>ylim[0] && x1+0.5*width<xlim[1] && y1+0.5*height<ylim[1]) )
{
boxes.push({
leftX: x1-0.5*width,
bottomY: y1-0.5*height,
width: width,
height: height,
icon: false,
id: data[i].id,
name: labelsInfo[data[i].id].text
});
data[i].update({
name: labelsInfo[data[i].id].text,
dataLabels: {
x: (x1 - data[i].x),
y: (data[i].y - y1)
}
}, false);
isOverlapped = false;
} else {
theta = theta+tstep;
r = r + rstep*tstep/(2*Math.PI);
x1 = x0+sdx*r*Math.cos(theta);
y1 = y0+sdy*r*Math.sin(theta);
}
}
}
// You may have to redraw the chart here
},
您可以在重绘时调用此功能,也可以优化调用此功能。
请注意,如果您有一些大点或形状或图标指示您的数据项所在,您必须检查是否有任何建议的解决方案也不会干扰(重叠)图标。
答案 1 :(得分:0)
您可以尝试调整此算法:
function StaggerDataLabels(series) {
sc = series.length;
if (sc < 2) return;
for (s = 1; s < sc; s++) {
var s1 = series[s - 1].points,
s2 = series[s].points,
l = s1.length,
diff, h;
for (i = 0; i < l; i++) {
if (s1[i].dataLabel && s2[i].dataLabel) {
diff = s1[i].dataLabel.y - s2[i].dataLabel.y;
h = s1[i].dataLabel.height + 2;
if (isLabelOnLabel(s1[i].dataLabel, s2[i].dataLabel)) {
if (diff < 0) s1[i].dataLabel.translate(s1[i].dataLabel.translateX, s1[i].dataLabel.translateY - (h + diff));
else s2[i].dataLabel.translate(s2[i].dataLabel.translateX, s2[i].dataLabel.translateY - (h - diff));
}
}
}
}
}
//compares two datalabels and returns true if they overlap
function isLabelOnLabel(a, b) {
var al = a.x - (a.width / 2);
var ar = a.x + (a.width / 2);
var bl = b.x - (b.width / 2);
var br = b.x + (b.width / 2);
var at = a.y;
var ab = a.y + a.height;
var bt = b.y;
var bb = b.y + b.height;
if (bl > ar || br < al) {
return false;
} //overlap not possible
if (bt > ab || bb < at) {
return false;
} //overlap not possible
if (bl > al && bl < ar) {
return true;
}
if (br > al && br < ar) {
return true;
}
if (bt > at && bt < ab) {
return true;
}
if (bb > at && bb < ab) {
return true;
}
return false;
}