Network / Force Directed Graph - Highcharts

author(s): Paweł Fus

by b_g_v

HTML

<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/networkgraph.js"></script>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>

<div id="container"></div>

CSS

#container{
  height: 900px;
}

JavaScript

(function(H) {
  H.wrap(H.seriesTypes.networkgraph.prototype.pointClass.prototype, 'getLinkPath', function(p) {
    //return ['M', 0, 0, 0, 0];
    var left = this.toNode,right = this.fromNode;

    var angle = Math.atan((left.plotX - right.plotX) / (left.plotY - right.plotY));

    if(this.linkOffset){
      if(left.plotX && right.plotX && (Math.abs(left.plotY - right.plotY) <= Math.abs(left.plotX - right.plotX))){
        left.plotX += this.linkOffset;
        right.plotX += this.linkOffset;
      }else{
        if(left.plotY && right.plotY){
          left.plotY += this.linkOffset;
          right.plotY += this.linkOffset;
        }
      }
    }

    if (angle && this.arrow) {
      let path = ['M', left.plotX, left.plotY, right.plotX, right.plotY],
        lastPoint = left,
        nextLastPoint = right,
        pointRadius = 50,
        arrowLength = 5,
        arrowWidth = 5;

      if (left.plotY < right.plotY) {
        path.push(
          nextLastPoint.plotX - pointRadius * Math.sin(angle),
          nextLastPoint.plotY - pointRadius * Math.cos(angle),
        );
        path.push(
          nextLastPoint.plotX - pointRadius * Math.sin(angle) - arrowLength * Math.sin(angle) - arrowWidth * Math.cos(angle),
          nextLastPoint.plotY - pointRadius * Math.cos(angle) - arrowLength * Math.cos(angle) + arrowWidth * Math.sin(angle),
        );
        path.push(
          nextLastPoint.plotX - pointRadius * Math.sin(angle),
          nextLastPoint.plotY - pointRadius * Math.cos(angle),
        );
        path.push(
          nextLastPoint.plotX - pointRadius * Math.sin(angle) - arrowLength * Math.sin(angle) + arrowWidth * Math.cos(angle),
          nextLastPoint.plotY - pointRadius * Math.cos(angle) - arrowLength * Math.cos(angle) - arrowWidth * Math.sin(angle),
        );
      } else {
        path.push(
          nextLastPoint.plotX + pointRadius * Math.sin(angle),
          nextLastPoint.plotY + pointRadius * Math.cos(angle),
        );
       ...