How to draw an allipse (oval) on a Highchart graph

1.1k views Asked by At

I have two series and their intersection point. I want to have an oval (ellipse) on a chart with center in intersection. Oval radiuses should be set in terms of axis units to show area of interest for each axis.

Highcharts.chart('container', {
    series: [
      // first series
      {
        name: 'IPR',
        data: [[0, 30.5],[18.5, 25.4],[30, 19.4],[38, 9.7],[42, 0.02]]
      }, 
      // second series
      {
        name: 'VLP', 
        data: [[2, 0.5],[7, 1],[14, 6],[21, 22],[29, 29.6],[40, 30.3],[50, 27.2]]
      }, 
      // intersection
      {
        name: 'Operating point',
        data: [
          [22.42, 23.35]
        ]
      }
    ],
})

How can I programmatically draw an oval in intersection and make zoom work?

3

There are 3 answers

1
Kamil Kulig On BEST ANSWER

You can use Renderer.createElement to create other SVG elements in Highcharts:

    this.renderer.createElement('ellipse').attr({
      cx: 60,
      cy: 60,
      rx: 50,
      ry: 25,
      'stroke-width': 2,
      stroke: 'red',
      fill: 'yellow',
      zIndex: 3
    }).add();

For translating to axis units use toPixels as @Anton Rybalko suggested.


Live demo: http://jsfiddle.net/kkulig/ds6aj5yp/

API references:

0
Anton Rybalko On

To draw a circle, line etc SVGRenderer can be used. But there is no method to draw an ellipse. However rect() with rounded corners can be used.

Following code can be used to draw an ellipse in point (100, 200) px, horizontal radius 20 px and vertical radius 10 px:

chart.renderer.rect(100, 100, 20, 10, '50%')
    .attr({
        'stroke-width': 1,
        'stroke': 'green',
        'fill': 'yellow',
        zIndex: 0
    })
    .add();

To specify x, y and radiuses in terms of axis untits Axis.toPixels() can be used. If we need to convert point (22.42, 23.35) to pixels it can be done like:

var x = chart.xAxis[0].toPixels(22.42),
    y = chart.yAxis[0].toPixels(23.35)

So function to draw an ellipse would be:

var drawEllipse = function(chart, x, y, xr, yr) {
  var x1 = chart.xAxis[0].toPixels(x-xr)
  var x2 = chart.xAxis[0].toPixels(x+xr)
  var y1 = chart.yAxis[0].toPixels(y-yr)
  var y2 = chart.yAxis[0].toPixels(y+yr)
  $('.' + rectClass).remove()
  chart.renderer.rect(x1, y2, x2 - x1, y1 - y2, '50%')
    .attr({
        'stroke-width': 1,
        'stroke': 'green',
        'fill': 'yellow',
        'zIndex': 0
    })
    .add();
};

Finnaly redraw event can be used to redraw ellipse after zoom:

$(function() {
  var drawEllipse = function(chart, x, y, xr, yr) {
    // get pixel coordinates of rect
    var x1 = chart.xAxis[0].toPixels(x-xr)
    var x2 = chart.xAxis[0].toPixels(x+xr)
    var y1 = chart.yAxis[0].toPixels(y-yr)
    var y2 = chart.yAxis[0].toPixels(y+yr)
    // remove previous ellipse
    var rectClass = 'operating-point-ellipse'
    $('.' + rectClass).remove()
    // draw ellipse using rect()
    chart.renderer.rect(x1, y2, x2 - x1, y1 - y2, '50%')
      .attr({
        'stroke-width': 1,
        'stroke': 'green',
        'fill': 'green',
        'fill-opacity': 0.2,
        'zIndex': 0
      })
      .addClass(rectClass)
      .add();
  };

  $('#container').highcharts({
    chart: {
      events: {
        redraw: function() {
          drawEllipse(this, 22.42, 23.35, 6, 3);
        },
        load: function() {
          drawEllipse(this, 22.42, 23.35, 6, 3);
        }
      }
    },
    //...
  });
});

See full code on jsFiddle: http://jsfiddle.net/arybalko/rcct2r0b/

1
Jonathan Nikkel On

The SVG Renderer is not really a great answer.

The polygon feature should be used (with many points, which you can generate offline in a backend, or analytically in the front end):

series: [{
        name: 'Target',
        type: 'polygon',
        data: [[153, 42], [149, 46], [149, 55], [152, 60], [159, 70], [170, 77], [180, 70],
            [180, 60], [173, 52], [166, 45]],
        color: Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0.5).get(),
        enableMouseTracking: false

    }

https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/demo/polygon/