Highcharts 散点图 - 如何修复重叠的数据标签?

标签 highcharts overlap scatter-plot

我看过很多关于这个主题的帖子,但这个问题似乎没有得到妥善解决。

我们有一个很大的散点,大约有 30 个点(没有什么压倒性的)。但在某些情况下,这些点会非常靠近或重叠(我想我们对此无能为力)。

主要问题是我们希望数据标签始终可见,并且当点彼此靠近时这些数据标签会重叠。

我们尝试过allowOverlap: false,但这并不是我们真正需要/想要的。我们理想的结果是允许所有数据标签显示在分散内的屏幕上,同时仍然能够始终读取每个数据标签。

我们是否通过调整点的间距或调整数据标签的间距/填充来解决此问题?有什么建议么?谢谢。

最佳答案

我还没有从 Highcharts 中找到此问题的有效配置解决方案(尽管我不能保证最新版本中没有)。然而,有一些算法可以对分割数据标签的标签坐标进行可接受的随机化。

以下是一些有用的链接,可以帮助您了解该算法:

wordcloud package in R (cloud.R是包含算法的文件)

direct labels package in 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
},

您可以在重绘时调用此函数或优化以减少调用它的频率。

请注意,如果您有一些大点、形状或图标指示数据项所在的位置,您将必须检查任何建议的解决方案是否不会干扰(重叠)图标。

关于Highcharts 散点图 - 如何修复重叠的数据标签?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29624572/

相关文章:

javascript - 统一呈现 Highcharts.js 图表而不是从左到右

javascript - Highcharts - 如何在 3D 散点图上的点工具提示(弹出窗口)中设置自定义内容或如何自定义点工具提示信息?

matlab - 避免 MATLAB 图形中的文本重叠

asynchronous - 如何异步调用DeviceIOControl代码?

javascript - 用于创建带有象限的散点图的库

r - 在散点图中绘制 95% 置信限

php - 如何从 MySQL DB 的多个表中获取数据并使用 PHP 对其进行操作以显示图形?

php - 使用 mysql 组合列和样条 Highcharts

JavaFX:使节点不占用空间,但让其父级决定其位置

python - Altair 条件颜色散点图