0

I have a web application that uses Dygraphs to create charts.

The application allows a user to create multiple Dygraph charts (each with their own Y-Axis) that will be stacked on top of each other.

Here's an example of what the multiple Dygraphs look like on a PC browser: Notice that the example displays three different Dygraphs each having their own Y-axis, but the X-axis is hidden for the top 2 charts and visible on the bottom chart.enter image description here

I will allow the user to save the chart to disk as a PNG. - The way I currently save the multiple Dygraphs as one PNG is:

  1. Create a target canvas that will be used to contain all the visible Dygraphs
  2. Extract each canvas out of each Dygraph, then add each canvas to the target canvas **
  3. Create a PNG via the .toDataURL() function on the target canvas

Here's an example of what the above screenshot looks like when saved as one PNG: (This is exactly what I want from the PNG) enter image description here

The procedure works fine on browsers on a PC. But when I attempt to save the multiple Dygraphs into one PNG on a phone/tablet browser, the resultant PNG doesn't match the graph that is visible on the screen.

Example: Here's what the multiple Dygraphs look like on an iPad (screenshot) enter image description here

And here's what the resultant PNG looks like (Notice how the width and height of each chart does not match the actual iPad display). enter image description here

I don't understand why the PNG is rendered correctly when I use a PC browser, but is not rendered correctly when I use a browser on a mobile device.

I'm not sure if this problem is due to limitations of the Canvas.toDataURL() function or if this is a Dygraphs problem or something else. I'm fishing for advice that may point me in the right direction and/or shed light on this particular problem.

**I should mention that I use Juan Manuel Caicedo Carvajal's Dygraph-Export extension

Jed
  • 10,649
  • 19
  • 81
  • 125

2 Answers2

0

I'm guessing the Problem occurs, because the generated canvas isn't rendered fully to the responsive screen of an iPad.

You can try to export the original canvas (instead of generating a new one with the said library) yourself with toDataUrl https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL

Dygraphs generates 2 canvas, one for the legend and one for the actual graph and lays them ontop of each other. So make sure you choose the right one (not the _hidden_canvas). If the examples works you can draw the legend onto the graph canvas with canvas.drawImage(otherCanvas) How to Copy Contents of One Canvas to Another Canvas Locally

Hope this helps. Keep me updated!

Community
  • 1
  • 1
Gordon Mohrin
  • 645
  • 1
  • 6
  • 17
0

My workaround/hack for the problem stated in my OP was to make a change to the Dygraph source in the Dygraph.getContextPixelRatio function.

Notice in the code below that I set devicePixelRatio = 1

dygraph-combined.js

Dygraph.getContextPixelRatio = function (context) {
try {
    //var devicePixelRatio = window.devicePixelRatio;
    var devicePixelRatio = 1; // Hack!!!  
    var backingStoreRatio = context.webkitBackingStorePixelRatio ||
        context.mozBackingStorePixelRatio ||
        context.msBackingStorePixelRatio ||
        context.oBackingStorePixelRatio ||
        context.backingStorePixelRatio || 1;
    if (devicePixelRatio !== undefined) {
        return devicePixelRatio / backingStoreRatio;
    } else {
        // At least devicePixelRatio must be defined for this ratio to make sense.
        // We default backingStoreRatio to 1: this does not exist on some browsers
        // (i.e. desktop Chrome).
        return 1;
    }
} catch (e) {
    return 1;
}
};

In my case, this hack fixed my problem (stated in the OP) and didn't negatively affect any other parts of my application that uses Dygraphs. That said, if you find a better/correct way to fix the problem stated in the OP, please share.

Jed
  • 10,649
  • 19
  • 81
  • 125