highcharts 如何在Highchart散点图中绘制数据标签到标记的连线

ajsxfq5m  于 2022-11-10  发布在  Highcharts
关注(0)|答案(1)|浏览(182)

我在一个.Net Core应用程序中使用HighCharts。我有一个散点图,我使用抖动来分离点。我需要显示指向点标记的数据标签,但它们重叠了。下面是我的代码:

@using Highsoft.Web.Mvc.Charts;
@using Highsoft.Web.Mvc.Charts.Rendering;
<script src="~/lib/highcharts/js/v10/highcharts.js"></script>
<script src="~/lib/highcharts/js/v10/highcharts-more.js"></script>
<script src="~/lib/highcharts/js/v10/annotations.js"></script>

<link rel="stylesheet" type="text/css" href="~/lib/highcharts/highcharts.css" />
<script type="text/javascript">
    $(function () {
             $('#container1').highcharts({
            chart: {
                 type: 'scatter',
                 zoomType: 'xy',
                 width: 1500,
                 height: 1000,
                 events: {
                     load: function () {
                         StaggerDataLabels(this.series);
                     },
                     redraw: function () {
                         var series = this.series;
                         setTimeout(function () {
                             StaggerDataLabels(series);
                         }, 1000);
                     }
                 },
            },
            credits: {
                enabled: false
            },
            legend: {
                enabled: false
            },
            title: {
                text: 'Impact vs Life Cycle Root Cause',
                style: {
                    fontSize: '24px',
                    color: 'black'
                },
            },
            xAxis: {
                gridLineWidth: 1,
                title: {
                    text: 'Impact',
                    style: {
                        fontSize: '20px',
                        color: 'black'
                    },
                },
                tickInterval: 1,
                min: 0,
                max: 6,
                showFirstLabel: false,
                showLastLabel: false,
                labels: {
                    formatter: function () {
                        return bcxAxislabelFormatter(this.value);
                    },
                }
            },
            yAxis: {
                title: {
                    text: 'Life Cycle Root Cause',
                    style: {
                        fontSize: '20px',
                        color: 'black'
                    },
                },
                tickInterval: 1,
                min: 0,
                max: 6,
                showFirstLabel: false,
                showLastLabel: false,
                labels: {
                    formatter: function () {
                        return bcyAxislabelFormatter(this.value);
                    },
                    rotation: -45,
                }
            },
            tooltip: {
                formatter: formatB1ToolTip,
            },
            plotOptions: {
               series: {
                    dataLabels: {
                       allowOverlap: true,
                       shape: 'connector',
                       enabled: true,
                       formatter: function () {
                        return (this.point.label);
                    }

            }
        },
                scatter: {
                    jitter: {
                        x: 0.24,
                        y: 0.24
                    },
            marker: {
                radius: 5,
                states: {
                    hover: {
                        enabled: true,
                        lineColor: 'rgb(100,100,100)'
                    }
                }
            },
            states: {
                hover: {
                    marker: {
                        enabled: false
                    }
                }
            },
            tooltip: {
                pointFormat: '{point.x} , {point.y} '
            }
        }
            },
            series: [{
                data:@Html.Raw(Newtonsoft.Json.JsonConvert.DeserializeObject(ViewData["scatter1"].ToString()))
            }]
        });
    });
        function handleClick(e) {

        var url = '@Url.Action("GetIssueData", "Chart")' + "?X=" + e.point.x + "&Y=" + e.point.y;
        $.get(url).done(function (data) {
            $('#DisplayDetailedContent').find('#modal-content2').html(data);
        });
        $(this).attr('data-target', '#modal-container2');
        $(this).attr('data-toggle', 'modal');
        $('#DisplayDetailedContent').find('#modal-container2').modal('show');

    }
    function formatB1ToolTip() {
        var ptx = bcxAxislabelFormatter(this.point.x);
        var pty = bcyAxislabelFormatter(this.point.y);
        return '<b>' + ptx + '/' + pty + '</b><br/>Total Issues: ' + this.point.z ;
    }

    function bcxAxislabelFormatter(x) {
        var label = "";
        if (x == '1') {
            label = "Minimal";
        } else if (x == '2') {
            label = "Minor";
        } else if (x == '3') {
            label = "Moderate";
        } else if (x == '4') {
            label = "Significant";
        } else {
            label = "Critical";
        }
        return label;
    }

    function bcyAxislabelFormatter(x) {
        var label = "";
        if (x == '1') {
            label = "Test & Ops";
        } else if (x == '2') {
            label = "Manufacturing";
        } else if (x == '3') {
            label = "Process & Review";
        } else if (x == '4') {
            label = "Design & Process";
        } else {
            label = "Requirements";
        }
        return label;
    }

    function StaggerDataLabels(series) {
        sc = series[0].points.length;
        for (x = 1; x < 6; x++) {
            for (y = 1; y < 6; y++) {
                for (z = 1; z < 6; z++) {

                var arr = [];
                for (s = 1; s < sc; s++) {
                    if (series[0].points[s - 1].dataLabels[0].element.point.x == x && series[0].points[s - 1].dataLabels[0].element.point.y == y) {
                        arr.push(series[0].points[s - 1]);
                    }
                }
                var ac = arr.length;
                if (ac > 1) {
                    for (s = 1; s < ac; s++) {
                        var s1 = arr[s - 1],
                            s2 = arr[s],
                            diffx,
                            diff, h;
                        if (s1.dataLabel && s2.dataLabel) {
                            diff = s1.dataLabel.y - s2.dataLabel.y;
                            h = s1.dataLabel.height + 1;
                            if (isLabelOnLabel(s1.dataLabel, s2.dataLabel)) {
                                if (diff < 0) s1.dataLabel.translate(s1.dataLabel.translateX, s1.dataLabel.translateY - (h + diff));
                                else s2.dataLabel.translate(s2.dataLabel.translateX, s2.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;
    }
</script>

<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
    <style type="text/css">
        .table1 .highcharts-background {
            stroke: black;
            stroke-width: 2px;
        }

        .table1 .highcharts-plot-border {
            stroke-width: 1px;
            stroke: gray;
        }

        .table1 .highcharts-plot-background {
            fill: url(#MyGradient)
        }

        .table1 .highcharts-axis-title {
            font-size: 14px;
        }
    </style>
    <defs>
        <linearGradient id="MyGradient" x1="0%" y1="100%" x2="100%" y2="0%">
            <stop offset="0%" stop-color="#02f512" />
            <stop offset="30%" stop-color="#F2E95D" />
            <stop offset="70%" stop-color="#F2E95D" />
            <stop offset="100%" stop-color="#f50202" />
        </linearGradient>
    </defs>
</svg>

@{
    ViewData["Title"] = "Privacy Policy";
}

<div id="DisplayDataContent">
    <div id="DisplayDetailedContent">
        <div id="modal-container2" class="modal fade" tabindex="-1">
            <div class="modal-dialog modal-lg">
                <div id="modal-content2" class="modal-content">
                </div>
            </div>
        </div>
    </div>

</div>
<div>
    <table class="table1" style="margin:auto">
        <tr>
            <td>
                Container
                <!--Bubble Chart-->
                <div id="container"></div>
            </td>
        </tr>
        <tr>
            <td>
                container 1
                <!--Bubble Chart-->
                <div id="container1"></div>
            </td>
        </tr>
    </table>
</div>

@section Scripts {

}
<script>
    $(function () {
        $('body').on('click', '.close_issues', function (e) {
            e.preventDefault();
            $('#DisplayDetailedContent').find('#modal-container2').modal('hide');
        })
    });
</script>

以下是我的数据集:

[
{"x":1,"y":2,"label":"Second Issue Title","id":null},
{"x":1,"y":2,"label":"Test Not Admin","id":null},
{"x":1,"y":2,"label":"Commit Quarter Test","id":null},
{"x":1,"y":2,"label":"this is a test 1","id":null},
{"x":1,"y":2,"label":"Security Marking Test 2","id":null},
{"x":1,"y":3,"label":"Create Commit Quarter History 3","id":null},
{"x":1,"y":3,"label":"Test of TinyMCE","id":null},
{"x":1,"y":4,"label":"TPPI Test","id":null},
{"x":2,"y":2,"label":"Test LMPI #2","id":null},
{"x":2,"y":2,"label":"Test TinyMCE Changes","id":null},
{"x":2,"y":2,"label":"Test Affected programs #1","id":null},
{"x":2,"y":2,"label":"Test Edge","id":null},
{"x":2,"y":3,"label":"Testing IssueID Loading","id":null},
{"x":2,"y":3,"label":"Third Test of Issue ID Creation","id":null},
{"x":2,"y":3,"label":"This is the title of the 1st issue which is a little longer than normal","id":null},
{"x":2,"y":3,"label":"This is a test","id":null},
{"x":2,"y":3,"label":"DELETED","id":null},
{"x":2,"y":3,"label":"Test","id":null},
{"x":2,"y":4,"label":"Yet another issue yup","id":null},
{"x":2,"y":4,"label":"Testing of Create an Issue page","id":null},
{"x":3,"y":1,"label":"Second test of IssueID Creation","id":null},
{"x":3,"y":2,"label":"New Issue on 10/19","id":null},
{"x":3,"y":3,"label":"this is a test ","id":null},
{"x":3,"y":3,"label":"Testing New IssueID Creation","id":null},
{"x":3,"y":3,"label":"Testing Root Cause Issues","id":null},
{"x":3,"y":4,"label":"DELETED","id":null},
{"x":3,"y":4,"label":"DELETED","id":null},
{"x":3,"y":4,"label":"test","id":null},
{"x":3,"y":5,"label":"DELETED","id":null},
{"x":3,"y":5,"label":"Security Marking Test 3","id":null},
{"x":4,"y":1,"label":"Testing of Issue ID4","id":null},
{"x":4,"y":2,"label":"Create Commit Quarter History 2","id":null},
{"x":4,"y":2,"label":"Lifecycle and Impact test","id":null},
{"x":4,"y":3,"label":"This is a test","id":null},
{"x":4,"y":3,"label":"New Functional Area Test","id":null},
{"x":4,"y":3,"label":"this is a test 1","id":null},
{"x":4,"y":3,"label":"DELETED","id":null},
{"x":4,"y":3,"label":"Test4","id":null},
{"x":4,"y":5,"label":"Name Test","id":null},
{"x":4,"y":5,"label":"Test of LMPI","id":null},
{"x":5,"y":2,"label":"test1","id":null},
{"x":5,"y":3,"label":"Edge Test 2","id":null},
{"x":5,"y":3,"label":"TPPI Test","id":null},
{"x":5,"y":3,"label":"Security Marking Test","id":null},
{"x":5,"y":5,"label":"Test2","id":null}
]

我看过以下帖子:how-to-render-a-line-from-datalabels-to-marker-on-graph-in-highcharts,但我不知道如何使用/调用以下函数:

Highcharts.SVGRenderer.prototype.symbols.connector = function(x, y, w, h, options) {
  var anchorX = options && options.anchorX,
    anchorY = options && options.anchorY,
    path,
    yOffset,
    lateral = w / 2,
    H = Highcharts;

  if (H.isNumber(anchorX) && H.isNumber(anchorY)) {

    path = ['M', anchorX, anchorY];

    // Prefer 45 deg connectors
    yOffset = y - anchorY;
    if (yOffset < 0) {
      yOffset = -h - yOffset;
    }
    if (yOffset < w) {
      lateral = anchorX < x + (w / 2) ? yOffset : w - yOffset;
    }

    // Anchor below label
    if (anchorY > y + h) {
      path.push('L', x + lateral, y + h);

      // Anchor above label
    } else if (anchorY < y) {
      path.push('L', x + lateral, y);

      // Anchor left of label
    } else if (anchorX < x) {
      path.push('L', x, y + h / 2);

      // Anchor right of label
    } else if (anchorX > x + w) {
      path.push('L', x + w, y + h / 2);
    }
  }
  return path || [];
};

如何绘制从标签到点的线?

dtcbnfnu

dtcbnfnu1#

您可以使用添加另一个散点序列,并对其进行一些修改以显示连接和dataLabels。

series: [{
      type: 'scatter',
      data: [{
        name: 'First',
        x: 0,
        y: 29.9,
        dataLabels: {
          enabled: false
        }
      }, {
        name: 'Second',
        x: 0.1,
        y: 39.9,
        dataLabels: {
          formatter: function() {
            return 'test label';
          },
          x: 20,
          y: 0
        },
        marker: {
          enabled: false,
          radius: 0
        }
      }],
    },
]

用于设置行为的选项图表,其中enableMouseTracking: false用于关闭鼠标跟踪,lineWidth: 1用于绘制线条(与点的连接),showInLegend: false用于隐藏图例中的系列。

plotOptions: {
    scatter: {
      states: {
        inactive: {
          enabled: false
        }
      },
      dataLabels: {
        enabled: true,
        allowOverlap: true,
        crop: false,
        overflow: 'allow',
        align: 'center',
        verticalAlign: 'bottom',
        useHTML: true,
      },
      lineWidth: 1,
      color: 'red',
      enableMouseTracking: false,
      showInLegend: false
    },
  }

实时演示:http://jsfiddle.net/BlackLabel/hpds8f0x/2/

相关问题