Search code examples
javascriptdygraphs

Dygraphs drawing a vertical line at mouse cursor


I would like to draw a full height vertical line on a Dygraph plot that follows the precise x position of the cursor (note: I would like it to follow the cursor between points, not just snap to points)

Is there a callback option provided by Dygraphs that would allow this?

As a bonus, is it possible to make it play nicely with synchronisation?

So far I have tried adding a mousemove event listener to the canvas to draw a line on every mousemove event. This ends up just clogging up the plot because I can't clear the previous drawn lines, they just amass with every mousemove event!

Any help much appreciated.

Cheers,

P

edit: I have possibly made some progress. This is hacky but does give the visual effect of a line following the cursor. However, it also overwrites the point highlighting behaviour of Dygraphs. I still need the point highlighting for synchronisation and display of closest point value in the legend.

const plot = new Dygraph(...)

function getCursorPosition(canvas, event) {
  const rect = canvas.getBoundingClientRect();
  const x = event.clientX - rect.left;
  const y = event.clientY - rect.top;
  return [x, y]
}

canvas.addEventListener('mousemove', function(e) {
  // redraw the plot
  const xrange = plot.xAxisRange();
  plot.updateOptions({dateWindow: xrange});

  // add a line
  const [x, y] =getCursorPosition(canvas, e);
  const { height } = canvas;
  ctx.beginPath();
  ctx.moveTo(x, 0);
  ctx.lineTo(x, height);
  ctx.closePath();
  ctx.stroke();
});

Solution

  • Take a look at the hairlines demo, which uses the Dygraph.Plugins.Crosshair plugin. This tracks the highlighted point using the select and deselect events and draws a hairline on its own canvas.

    It sounds like you're close with the mousemove event. I'm not sure what canvas refers to in your example, but it should be one that you create yourself and overlay on the dygraph chart, just like in the Crosshair example. Then you just need to clear the canvas before you draw the line:

      // add a line
      const [x, y] =getCursorPosition(canvas, e);
      const { height, width } = canvas;
      ctx.clearRect(0, 0, width, height);
      ctx.beginPath();
      ctx.moveTo(x, 0);
      ctx.lineTo(x, height);
      ctx.closePath();
      ctx.stroke();
    

    You might also be interested in the hairlines demo. You can drag the "flags" left and right. They sample from wherever the hairline crosses the curve.