c# - 如何在 Highchart 散点图中从数据标签到标记画线

我在 .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}
]

我看过以下帖子: https://stackoverflow.com/questions/43944182/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 || [];
};

如何从标签到点画一条线?

回答1

您可以添加另一个散点系列并对其进行一些修改以显示连接和数据标签。

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/

相似文章

flutter - 类别子类别

我的用户点有类别和子类别。我想显示带有类别和子类别的点。我必须怎么做?例子类别1子类别1点1点2点3点4子类别2点1点2点3点4类别2子类别1点1点2点3点4子类别2点1点2点3点4类别3子类别1点1...

java - 计算 dates 的夏令时问题

我需要从我从Excel读取的一个date计算Dates,问题是,例如,如果我读取31/10/202102:00:00并添加1小时,它应该在同一小时再次返回,因为有时间改变所以在03:00:00将再次是...