Search code examples
javascriptangularchartshighchartsvenn-diagram

How to draw connectors for venn diagram chart in Highcharts?


I was trying to achieve the below chart. However, there are two problems I am facing. I am able to create most of the charts. Here is the link to Working fiddle.

  1. Here I was able to get the data labels as shown in the image but I don't want to use the function. If it is possible, please tell me how?
  2. Second is the connecting lines between data labels and charts. This I was able to achieve even with any function. There is something called connector shape for pie chart in which we have one of the options as crookedLine. The connector lines in the below image look like that. Please help me, even with function.

Highcharts.chart('container', {
  chart: {
    type: 'venn',
    marginLeft: 350,
    events: {
      load: drawDataLabel
    }
  },
  title: {
    text: 'EXTERNAL IP MALWARE INFECTION SUMMARY'
  },
  subtitle: {
    text: '<span><b>85%</b> 85 IPS NOT INFETCED<span>',
    useHTML: true,
    style: {
      color: '#34c52d',
      fontWeight: 400,
      padding: '2px 20px',
      border: '2px solid #F2F2F2'
    }
  },
  exporting: {
    enabled: false
  },
  credits: {
    enabled: false
  },
  plotOptions: {
    venn: {
      borderColor: 'transparent'
    }
  },
  tooltip: {
    enabled: false
  },
  series: [{
    type: 'venn',
    dataLabels: {
      enabled: false,
      align: 'left'
    },
    data: [{
        sets: ['A'],
        name: "<div style='width:36vw; padding:0.3em; border: 2px solid #F2F2F2'>15 % IPs WITH MALWRAE INFECTION</div>",
        value: 10,
        color: '#ffb81c',
        dataLabels: {
          //x: series.dataLabel.x,
          x: 0,
          y: -70,
          color: '#FFB81C',
          //borderColor: '#F2F2F2',
          //borderWidth: 2,
          useHTML: true,
          style: {
            //width: 200,
            textOutline: 'none'
          }
        }
      }, {
        sets: ['B'],
        name: "<div style='width:36vw; padding:0.3em; border: 2px solid #F2F2F2'>5% 5 INFECTED WITH CNCs</div>",
        value: 5,
        color: '#ff8319',
        dataLabels: {
          //x: 'point.x',
          //x: -363,
          y: 0,
          color: '#FF8319',
          //borderColor: '#F2F2F2',
          //borderWidth: 2,
          useHTML: true,
          style: {
            //width: 200,
            textOutline: 'none'
          }
        }
      }, {
        sets: ['C'],
        value: 2,
        name: "<div style='width:36vw;  padding:0.3em; border: 2px solid #F2F2F2'>3% 3 IPs BLACKLISTED</div>",
        color: '#e30000',
        dataLabels: {
          //x: 'point.x',
          //x: -301,
          y: 70,
          color: '#e30000',
          //borderColor: '#F2F2F2',
          //borderWidth: 2,
          useHTML: true,
          style: {
            //width: 200,
            textOutline: 'none'
          }
        }
      },
      {
        sets: ['A', 'B'],
        value: 4.999,
        name: ' ',
        color: '#FF8319'
      },
      {
        sets: ['B', 'C'],
        value: 1.999,
        name: ' ',
        color: '#e30000'
      }
    ]
  }]
});

function drawDataLabel() {
  var points = this.series[0].points,
    point1R = points[0].shapeArgs.r;


  this.renderer.label('15 % IPs WITH MALWRAE INFECTION', 0, 150, 'rect', points[0].plotX + this.plotLeft, points[0].plotY + this.plotTop)
    .css({
      color: '#FFB81C'
    })
    .attr({
      width: 210,
      fill: '#FFFFFF',
      'stroke-width': 2,
      stroke: '#F2F2F2',
      padding: 5,
      fontWeight: 400,
      zIndex: 6
    })
    .add();

  this.renderer.label('5% 5 INFECTED WITH CNCs', 0, 270, 'rect', points[1].plotX + this.plotLeft, points[1].plotY + this.plotTop)
    .css({
      color: '#FF8319'
    })
    .attr({
      width: 210,
      fill: '#FFFFFF',
      'stroke-width': 2,
      stroke: '#F2F2F2',
      padding: 5,
      fontWeight: '400',
      zIndex: 6
    })
    .add();

  this.renderer.label('3% 3 IPs BLACKLISTED', 0, 210, 'rect', points[2].plotX + this.plotLeft, points[2].plotY + this.plotTop)
    .css({
      color: '#E30000'
    })
    .attr({
      width: 210,
      fill: '#FFFFFF',
      'stroke-width': 2,
      stroke: '#F2F2F2',
      padding: 5,
      fontWeight: '400',
      zIndex: 6
    })
    .add();
}
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/venn.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/export-data.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>

<figure class="highcharts-figure">
    <div id="container"></div>
</figure>

enter image description here


Solution

  • The answer is provided in the comment by @ppotaczek.

    Highcharts.chart('container', {
      chart: {
        type: 'venn',
        marginLeft: 350,
        events: {
          load: drawDataLabel
        }
      },
      title: {
        text: 'EXTERNAL IP MALWARE INFECTION SUMMARY'
      },
      subtitle: {
        text: '<span><b>85%</b> 85 IPS NOT INFETCED<span>',
        useHTML: true,
        style: {
          color: '#34c52d',
          fontWeight: 400,
          padding: '2px 20px',
          border: '2px solid #F2F2F2'
        }
      },
      exporting: {
        enabled: false
      },
      credits: {
        enabled: false
      },
      plotOptions: {
        venn: {
          borderColor: 'transparent'
        }
      },
      tooltip: {
        enabled: false
      },
      series: [{
        type: 'venn',
        dataLabels: {
          enabled: false,
          align: 'left'
        },
        data: [{
            sets: ['A'],
            name: "<div style='width:36vw; padding:0.3em; border: 2px solid #F2F2F2'>15 % IPs WITH MALWRAE INFECTION</div>",
            value: 10,
            color: '#ffb81c',
            dataLabels: {
              //x: series.dataLabel.x,
              x: 0,
              y: -70,
              color: '#FFB81C',
              //borderColor: '#F2F2F2',
              //borderWidth: 2,
              useHTML: true,
              style: {
                //width: 200,
                textOutline: 'none'
              }
            }
          }, {
            sets: ['B'],
            name: "<div style='width:36vw; padding:0.3em; border: 2px solid #F2F2F2'>5% 5 INFECTED WITH CNCs</div>",
            value: 5,
            color: '#ff8319',
            dataLabels: {
              //x: 'point.x',
              //x: -363,
              y: 0,
              color: '#FF8319',
              //borderColor: '#F2F2F2',
              //borderWidth: 2,
              useHTML: true,
              style: {
                //width: 200,
                textOutline: 'none'
              }
            }
          }, {
            sets: ['C'],
            value: 2,
            name: "<div style='width:36vw;  padding:0.3em; border: 2px solid #F2F2F2'>3% 3 IPs BLACKLISTED</div>",
            color: '#e30000',
            dataLabels: {
              //x: 'point.x',
              //x: -301,
              y: 70,
              color: '#e30000',
              //borderColor: '#F2F2F2',
              //borderWidth: 2,
              useHTML: true,
              style: {
                //width: 200,
                textOutline: 'none'
              }
            }
          },
          {
            sets: ['A', 'B'],
            value: 4.999,
            name: ' ',
            color: '#FF8319'
          },
          {
            sets: ['B', 'C'],
            value: 1.999,
            name: ' ',
            color: '#e30000'
          }
        ]
      }]
    });
    
    function drawDataLabel() {
      var points = this.series[0].points,
        point1R = points[0].shapeArgs.r;
        var data = this.series[0].data;
      var boxX = 5;
      var baseBoxY = 50;
      var baseLabelValueSvg = 20;
    
        console.clear();
        console.log(this.plotX, this.plotY, this.plotRight, this.plotLeft, this.plotTop);
      this.renderer.label('15 % IPs WITH MALWRAE INFECTION', boxX, (this.yAxis[0].right + (baseLabelValueSvg + (2.5 * baseBoxY))), 'rect', data[0].plotX, data[0].plotY, true)
        .css({
          color: '#FFB81C'
        })
        .attr({
          width: 210,
          fill: '#FFFFFF',
          'stroke-width': 2,
          stroke: '#F2F2F2',
          padding: 5,
          fontWeight: 400,
          zIndex: 6
        })
        .add();
    
      this.renderer.path(['M', 210, (this.yAxis[0].right + (baseLabelValueSvg + (2.5 * baseBoxY)))+12, 'L', this.plotLeft, (this.yAxis[0].right + (baseLabelValueSvg + (2.5 * baseBoxY)))+12, 420, 200]).attr({
        'stroke-width': 2,
        stroke: '#FFB81C'
      }).add();
    
    
      this.renderer.label('5% 5 INFECTED WITH CNCs',boxX, (this.yAxis[0].right + (baseLabelValueSvg + (5.1 * baseBoxY))), 'rect', data[1].plotX, data[1].plotY, true)
        .css({
          color: '#FF8319'
        })
        .attr({
          width: 210,
          fill: '#FFFFFF',
          'stroke-width': 2,
          stroke: '#F2F2F2',
          padding: 5,
          fontWeight: '400',
          zIndex: 6
        })
        .add();
    
      this.renderer.path(['M', 210, (this.yAxis[0].right + (baseLabelValueSvg + (5.1 * baseBoxY)))+12, 'L', this.plotLeft, (this.yAxis[0].right + (baseLabelValueSvg + (5.1 * baseBoxY)))+12, 420, 250]).attr({
        'stroke-width': 2,
        stroke: '#FF8319'
      }).add();
    
    
      this.renderer.label('3% 3 IPs BLACKLISTED', boxX, (this.yAxis[0].right + (baseLabelValueSvg + (3.8 * baseBoxY))), 'rect', data[2].plotX, data[2].plotY, true)
        .css({
          color: '#E30000'
        })
        .attr({
          width: 210,
          fill: '#FFFFFF',
          'stroke-width': 2,
          stroke: '#F2F2F2',
          padding: 5,
          fontWeight: '400',
          zIndex: 6
        })
        .add();
    
      this.renderer.path(['M', 210, (this.yAxis[0].right + (baseLabelValueSvg + (3.8 * baseBoxY)))+12, 'L', 420, (this.yAxis[0].right + (baseLabelValueSvg + (3.8 * baseBoxY)))+12]).attr({
        'stroke-width': 2,
        stroke: '#E30000'
      }).add();
    }
    <script src="https://code.highcharts.com/highcharts.js"></script>
    <script src="https://code.highcharts.com/modules/venn.js"></script>
    <script src="https://code.highcharts.com/modules/exporting.js"></script>
    <script src="https://code.highcharts.com/modules/export-data.js"></script>
    <script src="https://code.highcharts.com/modules/accessibility.js"></script>
    
    <figure class="highcharts-figure">
        <div id="container"></div>
    </figure>

    Anyone searching for an answer. Here is the final version based on this