我正在尝试在页面顶部绘制一个巨大的画布矩形(某种灯箱背景),代码非常简单:
var el = document.createElement('canvas');
el.style.position = 'absolute';
el.style.top = 0;
el.style.left = 0;
el.style.zIndex = 1000;
el.width = window.innerWidth + window.scrollMaxX;
el.height = window.innerHeight + window.scrollMaxY;
...
document.body.appendChild(el);
// and later
var ctx = el.getContext("2d");
ctx.fillStyle = "rgba(0, 0, 0, 0.4)";
ctx.fillRect(0, 0, el.width, el.height);
有时(并非总是)最后一行抛出:
组件返回失败代码:0x80004005(NS_ERROR_FAILURE)[nsIDOMCanvasRenderingContext2D.fillRect]
我一直猜测是因为图片大小还是因为画布下面的内容类型(例如嵌入式视频播放)而发生这种情况,但显然不是。
所以我正在寻找有关如何隔离和/或解决此问题的任何想法。
答案 0 :(得分:5)
查看nsIDOMCanvasRenderingContext2D.fillRect()
implementation(并通过它调用的函数) - 并没有太多条件会返回NS_ERROR_FAILURE
。只有在EnsureSurface()
或mThebes->CopyPath()
失败时才会发生这种情况。 EnsureSurface()
中的以下两行很可能是您问题的根源:
// Check that the dimensions are sane
if (gfxASurface::CheckSurfaceSize(gfxIntSize(mWidth, mHeight), 0xffff)) {
这里有什么检查:
width * height * 4
)的大小不能超过2 GB。如果违反了上述任何条件,EnsureSurface()
将返回false
,从而产生您看到的异常。请注意,以上是可以随时更改的实现细节,您不应该依赖它们。但它们可能会让您了解代码违反的特定限制。
答案 1 :(得分:1)
您可以应用try-catch逻辑。 Firefox似乎是唯一有点奇怪的浏览器。
el.width = window.innerWidth + window.scrollMaxX;
el.height = window.innerHeight + window.scrollMaxY;
// try first to draw something to check that the size is ok
try
{
var ctx = el.getContext("2d");
ctx.fillRect(0, 0, 1, 1);
}
// if it fails, decrease the canvas size
catch(err)
{
el.width = el.width - 1000;
el.height = el.height - 1000;
}
我没有找到任何可以告诉最大画布大小的变量。它因浏览器和浏览器以及设备而异。
检测最大画布大小的唯一交叉浏览器方法似乎是一个减小画布大小的循环,例如。 100px直到它不会产生错误。我测试了一个循环,这是检测最大画布大小的快速方法。因为其他浏览器在尝试绘制超大画布时不会抛出错误,所以最好尝试绘制例如。红色矩形并读取一个像素并检查它是否为红色。
最大化检测性能:
- 循环时,画布应该在DOM之外以最大化速度
- 将起始大小设置为众所周知的最大值,似乎是32,767px(SO:Maximum size of a <canvas> element)
- 你可以制作一个更加智能的循环,分叉最大尺寸:比如使用第一个更大的减小步骤(例如1000px),当达到可接受的尺寸时,尝试将尺寸增加500px。如果这是可接受的大小,则增加250px,依此类推。这样就可以在最少量的试验中找到最大值。