Dygraphs drawing a vertical line at mouse cursor

Viewed 1071

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();
});
2 Answers

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.

You need to install dygraphs and types/dygraphs npm i dygraphs --save npm i @types/dygraphs --save

Then you need to insert these lines to work with plugins:

require('./../../../../node_modules/dygraphs/src/extras/synchronizer.js'); declare var Dygraph:any;

Change the path in the require string according to your project and you can use the plugin while creating the graph. Sample code from my project which is working:

this.graph = new Dygraph(document.getElementById("graph"), this.data, { legend: 'always', drawPoints: true, animatedZooms: true, showRoller: true, plugins: [ new Dygraph['Plugins'].Crosshair({ direction: "vertical" }), ] })

I got it working in Angular 8 with Crosshair plugin. You can do the similar in other frameworks.

Related