Search code examples
javascriptdygraphs

How do I draw blocks with dygraphs


Instead of a typical time series line graph, I need to draw blocks as illustrated in the transition from diagram 1 to diagram 2 below. I have the drawCallback calculating the canvas coordinates for each point, as shown. But how do I actually draw the blocks? I also need to hide the original lines as well, although I could draw them in white I suppose. I have used the underlayCallback previously to draw background blocks, but these need to be in the foreground. I set up the loop to iterate through and draw blocks when the y coordinate changes, but there is no CTX here, like in underlayCallbacks.

Thank you, in advance.

            drawCallback: function (g, initial) {
                var newdata = [];
                var startcoord = g.toDomCoords(g.file_[0][0],g.file_[0][1]);
                var lowerlimit = g.toDomCoords(g.file_[0][0],minstage);
                console.log(lowerlimit);
                for (i=0; i<g.file_.length; i++) {
                    newdata[i] = g.toDomCoords(g.file_[i][0],g.file_[i][1]);
                    // when y changes, draw previous block
                    if (newdata[1] != startcoord[1]) {

                    }
                }

previous lines version

enter image description here

EDIT: Solution:

    function barChartPlotter(e) {
    var ctx = e.drawingContext;
    var points = e.points;

    // calculate the height of each block
    var limits1 = e.dygraph.toDomCoords(points[0][0],1);
    var limits2 = e.dygraph.toDomCoords(points[0][0],2);
    var height = limits2[1]-limits1[1];

    var bar_width = points[2].canvasx - points[1].canvasx;

    // Do the actual plotting.
    for (var i = 0; i < points.length; i++) {
        var p = points[i];
        var center_x = p.canvasx;

        // set colors
        switch (points[i].yval) {
            case 1:
                ctx.fillStyle = "#CC0000";
                ctx.strokeStyle = '#CC0000';
                break;
            case 2:
                ctx.fillStyle = "#00CC00";
                ctx.strokeStyle = '#00CC00';
                break;
            case 3:
                ctx.fillStyle = "#0000CC";
                ctx.strokeStyle = '#0000CC';
                break;
            case 4:
                ctx.fillStyle = "#CC00CC";
                ctx.strokeStyle = '#CC00CC';
                break;
        }

        ctx.fillRect(center_x - bar_width / 2, p.canvasy, bar_width, height-1);
        ctx.strokeRect(center_x - bar_width / 2, p.canvasy, bar_width, height-1);
    }
}

Perfectly rendered result: enter image description here


Solution

  • You might be better served by defining a custom plotter rather than using underlayCallback. The docs are a bit sparse, but it gives you the reference to the drawing context that you need:

    function barChartPlotter(e) {
      const {points, dygraph, drawingContext} = e;
      // ... draw whatever you like
    }
    

    View source on that demo page to get a sense for how it works.