元素的最大大小

我使用的画布元素高度为 6001000像素,宽度为几十万或几十万像素。但是,在一定数量的像素(显然是未知的)之后,画布不再显示我用 JS 绘制的形状。

有人知道有没有限制吗?

在 Chrome12和 Firefox4中都进行了测试。

112292 次浏览

根据 W3规格,width/height 接口是一个无符号的 long-so 0 to 4,294,967,295(如果我没记错这个数字——可能有些不对)。

编辑: 奇怪的是,它说无符号长,但它测试显示只是一个正常的长值作为最大值: 2147483647。Jsfiddle-47工作,但高达48和它恢复到默认。

2014年10月13日更新

所有测试的浏览器都限制了画布元素的高度/宽度,但是许多浏览器也限制了画布元素的总面积。我能够测试的浏览器的限制如下:

Chrome:

最大高度/宽度: 32,767像素
最大面积: 268,435,456像素(例如16,384 x 16,384)

火狐:

最大高度/宽度: 32,767像素
最大面积: 472,907,776像素(例如,22,528 x 20,992) < br/>

IE:

最大高度/宽度: 8,192像素
最大面积: 无效

IE 手机:

最大高度/宽度: 4,096像素
最大面积: 无效

其他:

我现在无法测试其他浏览器。有关其他限制,请参阅本页上的其他答案。


超过大多数浏览器的最大长度/宽度/面积会导致画布无法使用。(它会忽略任何绘图命令,即使是在可用区域。)IE 和 IE Mobile 将尊重可用空间内的所有绘制命令。

我遇到了内存不足的问题,Firefox 的画布高度大于8000,chrome 的处理能力似乎要高得多,至少要32000。

编辑: 在运行了一些测试之后,我发现 Firefox 16.0.2有一些非常奇怪的错误。

首先,我似乎从内存(在 javascript 中创建)画布获得了不同于 html 声明的画布的行为。

其次,如果没有合适的 html 标记和 meta 字符集,则画布可能限制为8196,否则可以到达32767。

第三,如果获得画布的2d 上下文,然后更改画布大小,那么您也可能被限制为8196。只需在获取2d 上下文之前设置画布大小,就可以在不出现内存错误的情况下获得最多32767。

我还没有能够始终如一地得到内存错误,有时它只是在第一页加载,然后随后的高度变化的工作。这是我用 http://pastebin.com/zK8nZxdE测试的 html 文件。

即使画布允许您放高度 = 2147483647,当您开始绘制时,什么也不会发生

只有当我把高度调回到32767时,绘画才会发生

Safari (所有平台)的限制要低得多。

已知的 iOS/Safari 限制

例如,我有一个6400x6400px 的画布缓冲区,上面绘制了数据。通过跟踪/导出内容并在其他浏览器上进行测试,我能够看到一切都很好。但是在 Safari 上,它会跳过在我的主上下文中绘制这个特定的缓冲区。

IOS 最大画布尺寸(宽 x 高) :

 iPod Touch 16GB = 1448x1448
iPad Mini       = 2290x2289
iPhone 3        = 1448x1448
iPhone 5        = 2290x2289

于2014年3月测试。

在@FredericCharette 上详述一下答案: 根据 狩猎旅行的内容指南中“了解 iOS 资源限制”一节:

对于内存小于256MB 的设备,画布元素的最大尺寸为300万像素,对于内存大于或等于256MB 的设备,最大尺寸为500万像素

因此,5242880(5 x 1024 x 1024)像素的任何大小变化都可以在大型内存设备上工作,否则就是3145728像素。

例如500万像素的画布(宽 x 高) :

Any total <= 5242880
--------------------
5 x 1048576 ~= 5MP   (1048576 = 1024 x 1024)
50 x 104857 ~= 5MP
500 x 10485 ~= 5MP

等等。

最大的正方形画布是(“ MiB”= 1024x1024字节) :

device < 256 MiB   device >= 256 MiB   iPhone 6 [not confirmed]
-----------------  -----------------   ---------------------
<= 3145728 pixels  <= 5242880 pixels   <= 16 x 1024 x 1024 p
1773 x 1773        2289 x 2289         4096 x 4096

在电脑上 -
我不认为有一个限制,但是是的,你可以走出内存异常。

在流动装置上-
以下是对移动设备的画布的限制:-

对于内存小于256MB 的设备,画布元素的最大尺寸为300万像素,对于内存大于或等于256MB 的设备,最大尺寸为500万像素。

例如,如果你想支持苹果的旧硬件,你的画布不能超过2048 × 1464。

希望这些资源能够帮助你走出困境。

IOS 有不同的限制。

使用 iOS7模拟器,我能够演示这个限制是5MB,如下所示:

var canvas = document.createElement('canvas');
canvas.width = 1024 * 5;
canvas.height = 1024;
alert(canvas.toDataURL('image/jpeg').length);
// prints "110087" - the expected length of the dataURL

但是如果我把画布放大一行像素:

var canvas = document.createElement('canvas');
canvas.width = 1024 * 5;
canvas.height = 1025;
alert(canvas.toDataURL('image/jpeg'));
// prints "data:," - a broken dataURL

我试图通过编程方式找出这个限制: 从35000开始设置画布大小,逐步减少100直到找到有效的大小。在每个步骤中写入右下角的像素,然后读取它。它的工作-谨慎。

速度是可以接受的,如果宽度或高度设置为一些低值(例如10-200)这样: get_max_canvas_size('height', 20)

但是,如果调用没有宽度或高度像 get_max_canvas_size(),创建的画布是如此之大,以至于阅读单个像素的颜色是非常缓慢的,并且在 IE 中导致严重的挂起。

如果这样的测试可以做某种方式而不读取像素值,速度将是可以接受的。

当然,检测最大大小的最简单方法是查询最大宽度和高度的本机方法。但是 Canvas 是“一种生活标准”,所以也许有一天它会到来。

Http://jsfiddle.net/timo2012/tcg6363r/2/ (请注意! 您的浏览器可能挂起!)

if (!Date.now)
{
Date.now = function now()
{
return new Date().getTime();
};
}


var t0 = Date.now();
//var size = get_max_canvas_size('width', 200);
var size = get_max_canvas_size('height', 20);
//var size = get_max_canvas_size();
var t1 = Date.now();
var c = size.canvas;
delete size.canvas;
$('body').append('time: ' + (t1 - t0) + '<br>max size:' + JSON.stringify(size) + '<br>');
//$('body').append(c);


function get_max_canvas_size(h_or_w, _size)
{
var c = document.createElement('canvas');
if (h_or_w == 'height') h = _size;
else if (h_or_w == 'width') w = _size;
else if (h_or_w && h_or_w !== 'width' && h_or_w !== 'height' || !window.CanvasRenderingContext2D)
return {
width: null,
height: null
};
var w, h;
var size = 35000;
var cnt = 0;
if (h_or_w == 'height') w = size;
else if (h_or_w == 'width') h = size;
else
{
w = size;
h = size;
}


if (!valid(w, h))
for (; size > 10; size -= 100)
{
cnt++;
if (h_or_w == 'height') w = size;
else if (h_or_w == 'width') h = size;
else
{
w = size;
h = size;
}
if (valid(w, h)) break;
}
return {
width: w,
height: h,
iterations: cnt,
canvas: c
};


function valid(w, h)
{
var t0 = Date.now();
var color, p, ctx;
c.width = w;
c.height = h;
if (c && c.getContext)
ctx = c.getContext("2d");
if (ctx)
{
ctx.fillStyle = "#ff0000";
try
{
ctx.fillRect(w - 1, h - 1, 1, 1);
p = ctx.getImageData(w - 1, h - 1, 1, 1).data;
}
catch (err)
{
console.log('err');
}


if (p)
color = p[0] + '' + p[1] + '' + p[2];
}
var t1 = Date.now();


if (color == '25500')
{
console.log(w, h, true, t1 - t0);
return true;
}
console.log(w, h, false, t1 - t0);
return false;
}
}

您可以对它进行组块,然后在 javascript 中根据需要自动添加尽可能多的小画布,并在适当的画布上绘制元素。您最终可能仍然会耗尽内存,但是会达到单个画布的限制。

我不知道如何检测最大可能的大小没有迭代,但你可以检测如果一个给定的画布大小工程填写像素,然后读出颜色回来。如果画布没有呈现,那么您得到的颜色将不匹配。W

部分代码:

function rgbToHex(r, g, b) {
if (r > 255 || g > 255 || b > 255)
throw "Invalid color component";
return ((r << 16) | (g << 8) | b).toString(16);
}
var test_colour = '8ed6ff';
working_context.fillStyle = '#' + test_colour;
working_context.fillRect(0,0,1,1);
var colour_data = working_context.getImageData(0, 0, 1, 1).data;
var colour_hex = ("000000" + rgbToHex(colour_data[0], colour_data[1], colour_data[2])).slice(-6);

当您使用 WebGL 画布时,浏览器(包括桌面浏览器)会对底层缓冲区的大小施加额外的限制。即使你的画布很大,比如16,000 x16,000,大多数浏览器也会渲染一个更小的图片(比如4096x4096) ,然后放大。这可能会导致丑陋的像素化等。

我写了一些代码,以确定最大大小使用指数搜索,如果有人需要它。determineMaxCanvasSize()是您感兴趣的函数。

function makeGLCanvas()
{
// Get A WebGL context
var canvas = document.createElement('canvas');
var contextNames = ["webgl", "experimental-webgl"];
var gl = null;
for (var i = 0; i < contextNames.length; ++i)
{
try
{
gl = canvas.getContext(contextNames[i], {
// Used so that the buffer contains valid information, and bytes can
// be retrieved from it. Otherwise, WebGL will switch to the back buffer
preserveDrawingBuffer: true
});
}
catch(e) {}
if (gl != null)
{
break;
}
}
if (gl == null)
{
alert("WebGL not supported.\nGlobus won't work\nTry using browsers such as Mozilla " +
"Firefox, Google Chrome or Opera");
// TODO: Expecting that the canvas will be collected. If that is not the case, it will
// need to be destroyed somehow.
return;
}


return [canvas, gl];
}


// From Wikipedia
function gcd(a,b) {
a = Math.abs(a);
b = Math.abs(b);
if (b > a) {var temp = a; a = b; b = temp;}
while (true) {
if (b == 0) return a;
a %= b;
if (a == 0) return b;
b %= a;
}
}


function isGlContextFillingTheCanvas(gl) {
return gl.canvas.width == gl.drawingBufferWidth && gl.canvas.height == gl.drawingBufferHeight;
}


// (See issue #2) All browsers reduce the size of the WebGL draw buffer for large canvases
// (usually over 4096px in width or height). This function uses a varian of binary search to
// find the maximum size for a canvas given the provided x to y size ratio.
//
// To produce exact results, this function expects an integer ratio. The ratio will be equal to:
// xRatio/yRatio.
function determineMaxCanvasSize(xRatio, yRatio) {
// This function works experimentally, by creating an actual canvas and finding the maximum
// value, the browser allows.
[canvas, gl] = makeGLCanvas();


// Reduce the ratio to minimum
gcdOfRatios = gcd(xRatio, yRatio);
[xRatio, yRatio] = [xRatio/gcdOfRatios, yRatio/gcdOfRatios];


// if the browser cannot handle the minimum ratio, there is not much we can do
canvas.width = xRatio;
canvas.height = yRatio;


if (!isGlContextFillingTheCanvas(gl)) {
throw "The browser is unable to use WebGL canvases with the specified ratio: " +
xRatio + ":" + yRatio;
}


// First find an upper bound
var ratioMultiple = 1;  // to maintain the exact ratio, we will keep the multiplyer that
// resulted in the upper bound for the canvas size
while (isGlContextFillingTheCanvas(gl)) {
canvas.width *= 2;
canvas.height *= 2;
ratioMultiple *= 2;
}


// Search with minVal inclusive, maxVal exclusive
function binarySearch(minVal, maxVal) {
if (minVal == maxVal) {
return minVal;
}


middle = Math.floor((maxVal - minVal)/2) + minVal;


canvas.width = middle * xRatio;
canvas.height = middle * yRatio;


if (isGlContextFillingTheCanvas(gl)) {
return binarySearch(middle + 1, maxVal);
} else {
return binarySearch(minVal, middle);
}
}


ratioMultiple = binarySearch(1, ratioMultiple);
return [xRatio * ratioMultiple, yRatio * ratioMultiple];
}

也在 jsfiddle https://jsfiddle.net/1sh47wfk/1/

被接受的答案是过时的和不完整的。

浏览器对画布大小有不同的限制,但是这些限制通常会随着平台和硬件的不同而改变。这使得很难使用诸如“ [browser]的最大画布 [area/height/width][value]”这样的语句,因为 [value]可以基于操作系统、可用 RAM 或 GPU 类型进行更改。

使用大型 HTML <canvas>元素有两种方法:

  1. 将画布尺寸限制为可以在所有支持的平台上工作的尺寸。
  2. 在呈现之前以编程方式确定客户端上的画布限制。

那些希望以编程方式确定客户端画布限制的人应该考虑使用 帆布大小

  • GitHub : < a href = “ https://GitHub.com/jhildenbiddle/Canvasesize”rel = “ norefrer”> https://GitHub.com/jhildenbiddle/canvas-size
  • NPM : < a href = “ https://www.npmjs.com/package/cab- size”rel = “ norefrer”> https://www.npmjs.com/package/canvas-size

来自文件:

HTML 画布元素受到现代和传统元素的广泛支持 浏览器,但每个浏览器和平台的组合强加独特的 大小限制,超过这个限制将导致画布无法使用。 不幸的是,浏览器没有提供一种方法来确定它们的 限制是,也没有提供任何类型的反馈后,一个 无法使用的帆布已被创建。这使工作与大帆布 元素,特别是对于支持 浏览器和平台的多样性。

此微库提供了 HTML 画布元素所支持的浏览器以及能够 测试自定义画布尺寸 新的画布元素被创建,应用程序能够可靠地设置 画布尺寸在每个 浏览器/平台。

你可在此查阅各种平台及浏览器组合的测试结果:

  • 测试结果 : < a href = “ https://github.com/jhildenbiddle/画布大小 # Test-Results”rel = “ noReferrer”> https://github.com/jhildenbiddle/canvas-size#Test-Results

老实说,我是图书馆的作者。我在2014年创建了它,最近为一个新的画布相关项目重新审视了代码。我惊讶地发现,在2018年同样缺乏检测画布大小限制的可用工具,所以我更新了代码,发布了它,并希望它能帮助其他遇到类似问题的人。