在移动设备上将多个 Dygraph 保存为 PNG 时出现渲染问题
Rendering problems when saving multiple Dygraphs as a PNG on mobile devices
我有一个使用 Dygraphs 创建图表的 Web 应用程序。
该应用程序允许用户创建多个 Dygraph 图表(每个图表都有自己的 Y 轴),这些图表将彼此堆叠。
这里是多个 Dygraphs 在 PC 浏览器上的样子的示例:请注意,该示例显示了三个不同的 Dygraphs,每个都有自己的 Y 轴,但 X 轴对于前 2 个图表是隐藏的并且是可见的在底部图表上。
我将允许用户将图表以 PNG 格式保存到磁盘。 - 我目前将多个 Dygraphs 保存为一个 PNG 的方式是:
- 创建一个目标 canvas,它将用于包含所有可见的 Dygraphs
- 从每个 Dygraph 中提取每个 canvas,然后将每个 canvas 添加到目标 canvas **
- 通过目标上的 .toDataURL() 函数创建 PNG canvas
下面是上面的屏幕截图保存为一个 PNG 时的样子的示例:(这正是我想要的 PNG)
该程序在 PC 上的浏览器上运行良好。但是当我试图在 phone/tablet 浏览器上将多个 Dygraphs 保存到一个 PNG 中时,生成的 PNG 与屏幕上可见的图形不匹配。
示例:
这是 iPad 上多个 Dygraph 的样子(屏幕截图)
这是生成的 PNG 的样子(请注意每个图表的宽度和高度如何与实际 iPad 显示不匹配)。
我不明白为什么我使用PC 浏览器时PNG 可以正确呈现,但在移动设备上使用浏览器时无法正确呈现。
我不确定这个问题是由于 Canvas.toDataURL() 函数的限制还是 Dygraphs 问题或其他问题。我正在寻找可能为我指明正确方向的建议 and/or 阐明这个特定问题。
**我应该提到我使用 Juan Manuel Caicedo Carvajal's Dygraph-Export extension
我猜问题出现了,因为生成的 canvas 没有完全呈现到 iPad 的响应屏幕。
您可以尝试使用 toDataUrl https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL
自己导出原始 canvas(而不是使用上述库生成新的)
Dygraphs 生成 2 个 canvas,一个用于图例,一个用于实际图表,并将它们叠加在一起。因此,请确保您选择了正确的(而不是 _hidden_canvas)。如果示例有效,您可以使用 canvas.drawImage(otherCanvas) 将图例绘制到图 canvas 上
How to Copy Contents of One Canvas to Another Canvas Locally
希望这对您有所帮助。让我更新!
我的 workaround/hack 针对我的 OP 中所述的问题是在 Dygraph.getContextPixelRatio
函数中更改 Dygraph 源。
注意下面的代码我设置了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;
}
};
就我而言,这个 hack 解决了我的问题(在 OP 中说明)并且没有对我的应用程序中使用 Dygraphs
的任何其他部分产生负面影响。也就是说,如果您找到 better/correct 解决 OP 中所述问题的方法,请分享。
我有一个使用 Dygraphs 创建图表的 Web 应用程序。
该应用程序允许用户创建多个 Dygraph 图表(每个图表都有自己的 Y 轴),这些图表将彼此堆叠。
这里是多个 Dygraphs 在 PC 浏览器上的样子的示例:请注意,该示例显示了三个不同的 Dygraphs,每个都有自己的 Y 轴,但 X 轴对于前 2 个图表是隐藏的并且是可见的在底部图表上。
我将允许用户将图表以 PNG 格式保存到磁盘。 - 我目前将多个 Dygraphs 保存为一个 PNG 的方式是:
- 创建一个目标 canvas,它将用于包含所有可见的 Dygraphs
- 从每个 Dygraph 中提取每个 canvas,然后将每个 canvas 添加到目标 canvas **
- 通过目标上的 .toDataURL() 函数创建 PNG canvas
下面是上面的屏幕截图保存为一个 PNG 时的样子的示例:(这正是我想要的 PNG)
该程序在 PC 上的浏览器上运行良好。但是当我试图在 phone/tablet 浏览器上将多个 Dygraphs 保存到一个 PNG 中时,生成的 PNG 与屏幕上可见的图形不匹配。
示例:
这是 iPad 上多个 Dygraph 的样子(屏幕截图)
这是生成的 PNG 的样子(请注意每个图表的宽度和高度如何与实际 iPad 显示不匹配)。
我不明白为什么我使用PC 浏览器时PNG 可以正确呈现,但在移动设备上使用浏览器时无法正确呈现。
我不确定这个问题是由于 Canvas.toDataURL() 函数的限制还是 Dygraphs 问题或其他问题。我正在寻找可能为我指明正确方向的建议 and/or 阐明这个特定问题。
**我应该提到我使用 Juan Manuel Caicedo Carvajal's Dygraph-Export extension
我猜问题出现了,因为生成的 canvas 没有完全呈现到 iPad 的响应屏幕。
您可以尝试使用 toDataUrl https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL
自己导出原始 canvas(而不是使用上述库生成新的)Dygraphs 生成 2 个 canvas,一个用于图例,一个用于实际图表,并将它们叠加在一起。因此,请确保您选择了正确的(而不是 _hidden_canvas)。如果示例有效,您可以使用 canvas.drawImage(otherCanvas) 将图例绘制到图 canvas 上 How to Copy Contents of One Canvas to Another Canvas Locally
希望这对您有所帮助。让我更新!
我的 workaround/hack 针对我的 OP 中所述的问题是在 Dygraph.getContextPixelRatio
函数中更改 Dygraph 源。
注意下面的代码我设置了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;
}
};
就我而言,这个 hack 解决了我的问题(在 OP 中说明)并且没有对我的应用程序中使用 Dygraphs
的任何其他部分产生负面影响。也就是说,如果您找到 better/correct 解决 OP 中所述问题的方法,请分享。