<canvas>元素的最大大小</canvas>

时间:2011-05-21 11:40:01

标签: javascript html5 canvas

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

有没有人知道是否有限制?

在Chrome 12和Firefox 4中都进行了测试。

14 个答案:

答案 0 :(得分:107)

2014年10月13日更新

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

铬:

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

的Firefox:

最大高度/宽度:32,767像素
最大面积:472,907,7​​76像素(例如,22,528 x 20,992)

IE:

最大高度/宽度:8,192像素
最大面积:N / A

IE Mobile:

最大高度/宽度:4,096像素
最大面积:N / A

其他:

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


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

答案 1 :(得分:16)

我在Firefox上遇到内存不足错误,画布高度超过8000,Chrome似乎处理得更高,至少达到32000。

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

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

其次,如果你没有正确的html标签和元字符集,画布可能会被限制为8196,否则你最多可以达到32767.

第三,如果获得画布的2d上下文然后更改画布大小,则可能也限制为8196。在抓取2d上下文之前简单地设置画布大小允许您最多拥有32767而不会出现内存错误。

我无法始终如一地获取内存错误,有时它只在第一页加载时,然后后续高度更改才有效。这是我用http://pastebin.com/zK8nZxdE测试的html文件。

答案 2 :(得分:14)

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

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

于2014年3月进行了测试。

答案 3 :(得分:11)

要扩展@FredericCharette答案: 根据{#3}}部分&#34;了解iOS资源限制&#34;:

  

对于RAM小于256 MB的设备,画布元素的最大大小为3百万像素,对于大于或等于256 MB RAM的设备,最大大小为5百万像素

因此,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

依旧......

最大的SQUARE画布是(&#34; MiB&#34; = 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

答案 4 :(得分:7)

根据w3 specs,宽度/高度接口是无符号长 - 所以0到4,294,967,295(如果我记得那个数字正确 - 可能会偏离一些)。

编辑:奇怪的是,它表示unsigned long,但它测试只显示一个正常的长值,因为最大值:2147483647. Jsfiddle - 47可以工作,但最多可以恢复为48,然后恢复为默认值。

答案 5 :(得分:7)

即使画布允许你放置高度= 2147483647,当你开始画画时,什么都不会发生

只有当我将高度恢复到32767

时才会进行绘图

答案 6 :(得分:7)

iOS有不同的限制。

使用iOS 7模拟器,我能够证明限制为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

答案 7 :(得分:5)

在PC上
我认为没有限制,但是你可以忘记内存异常。

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

对于RAM小于256 MB的设备,画布元素的最大大小为3百万像素;对于RAM大于或等于256 MB的设备,最大大小为5百万像素。

所以例如 - 如果你想支持Apple的旧硬件,你的画布大小不能超过2048×1464。

希望这些资源可以帮助你解决问题。

答案 8 :(得分:5)

2018年更新

随着时间的流逝,画布的局限性发生了变化。可悲的是,没有改变的是,浏览器仍然无法通过Canvas API提供有关画布大小限制的信息。

对于那些希望以编程方式确定浏览器的最大画布尺寸或测试对自定义画布尺寸的支持的用户,请查看canvas-size

从文档中

  

HTML画布元素受到现代和传统的广泛支持   浏览器,但每种浏览器和平台的组合都具有独特性   尺寸限制,超过该尺寸限制将导致画布无法使用。   不幸的是,浏览器无法提供一种方法来确定其   局限性是,它们也不会在   无法使用的画布已创建。这使得使用大画布   挑战,特别是对于支持   各种浏览器和平台。

     

此微型库提供了最大面积,高度和宽度   浏览器支持的HTML canvas元素以及   测试自定义画布尺寸。通过在   创建了新的canvas元素,应用程序能够可靠地设置   画布尺寸在每个尺寸限制内   浏览器/平台。

test results中有一个演示链接和README,还有一个known issues部分,其中介绍了性能和虚拟机注意事项。

完全公开,我是图书馆的作者。我在2014年创建了它,最近又重新访问了与画布相关的新项目的代码。令我感到惊讶的是,在2018年仍然缺少可用于检测画布大小限制的工具,因此我更新了代码,并发布了它,并希望它可以帮助其他遇到类似问题的人。

答案 9 :(得分:3)

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

Known iOS/Safari Limitations

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

答案 10 :(得分:3)

我尝试以编程方式找出限制:从35000开始设置画布大小,逐步减少100直到找到有效大小。在编写右下像素然后读取它的每一步中。它很有效 - 谨慎。

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

但如果没有像get_max_canvas_size()这样的宽度或高度调用,则创建的画布非常大,以至于读取SINGLE像素颜色非常慢,并且在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;
  }
}

答案 11 :(得分:3)

当您使用WebGL画布时,浏览器(包括桌面浏览器)将对底层缓冲区的大小施加额外限制。即使你的画布很大,例如16,000x16,000,大多数浏览器将呈现更小(让我们说4096x4096)的图片,并进行扩展。这可能导致丑陋的像素化等。

如果有人需要,我已经编写了一些代码来确定使用指数搜索的最大大小。 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]; } 是您感兴趣的功能。

django.setup()

同样在jsfiddle https://jsfiddle.net/1sh47wfk/1/

答案 12 :(得分:1)

你可以将它分块并在javascript中根据需要添加尽可能多的小画布并在适当的画布上绘制元素。您最终可能仍然会耗尽内存,但会通过单个画布限制来获取。

答案 13 :(得分:0)

我不知道如何在没有迭代的情况下检测最大可能的大小,但是您可以通过填充像素然后再读出颜色来检测给定的画布大小是否有效。如果画布未渲染,则返回的颜色将不匹配。 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);