Максимальный размер элемента <canvas>
Я работаю с элементом canvas с высотой от 600
до 1000
пикселей и шириной в несколько десятков или сотен тысяч пикселей. Однако после определенного количества пикселей (очевидно, неизвестных) холст больше не отображает формы, которые я рисую с помощью JS.
Кто-нибудь знает, есть ли предел?
Протестировано как в Chrome 12, так и в Firefox 4.
Ответы
Ответ 1
Обновлено 10/13/2014
Все проверенные браузеры имеют ограничения на высоту/ширину элементов холста, но многие браузеры также ограничивают общую площадь элемента canvas. Для браузеров, которые я могу проверить, ограничения следующие:
Chrome:
Максимальная высота/ширина: 32,767 пикселей
Максимальная площадь: 268 435 456 пикселей (например, 16,384 x 16,384)
Firefox:
Максимальная высота/ширина: 32 767 пикселей
IE:
Максимальная высота/ширина: 8,192 пикселя
Максимальная площадь: N/A
IE Mobile:
Максимальная высота/ширина: 4 096 пикселей
Максимальная площадь: N/A
Другое:
В настоящее время я не могу протестировать другие браузеры. Дополнительную информацию см. В других ответах на этой странице.
Превышение максимальной длины/ширины/области в большинстве браузеров делает невозможным использование холста. (Он игнорирует любые команды рисования даже в полезной области.) IE и IE Mobile будут выполнять все команды рисования в используемом пространстве.
Ответ 2
Я столкнулся с ошибками памяти в Firefox с высотой холста больше 8000, хром, похоже, обрабатывает гораздо больше, по крайней мере до 32000.
EDIT: после запуска еще нескольких тестов я обнаружил некоторые очень странные ошибки в Firefox 16.0.2.
Во-первых, я, кажется, получаю другое поведение из памяти (созданного в javascript) canvas, а не html объявленного холста.
Во-вторых, если у вас нет правильного html-тега и мета-кодировки, холст может быть ограничен 8196, в противном случае вы можете перейти до 32767.
В-третьих, если вы получите 2d-контекст холста, а затем измените размер холста, вы можете быть ограничены также 8196. Просто установив размер холста, прежде чем захватить 2d-контекст, вы можете иметь до 32767 без ошибок памяти.
Я не смог последовательно получить ошибки памяти, иногда это только при загрузке первой страницы, а затем последующие изменения высоты работы. Это html файл, который я тестировал с помощью http://pastebin.com/zK8nZxdE.
Ответ 3
Размер холста iOS max (ширина x высота):
iPod Touch 16GB = 1448x1448
iPad Mini = 2290x2289
iPhone 3 = 1448x1448
iPhone 5 = 2290x2289
протестирован в марте 2014 года.
Ответ 4
Чтобы немного расширить ответ @FredericCharette:
По руководство по содержанию сафари в разделе "Знать ограничения ресурсов iOS":
Максимальный размер элемента canvas составляет 3 мегапикселя для устройств с ОЗУ менее 256 МБ и 5 мегапикселей для устройств с большей или равной 256 МБ ОЗУ.
Поэтому любое изменение размера пикселей 5242880 (5 x 1024 x 1024) будет работать на больших устройствах памяти, в противном случае это 3145728 пикселей.
Пример для 5-мегапиксельного холста (ширина х высота):
Any total <= 5242880
--------------------
5 x 1048576 ~= 5MP (1048576 = 1024 x 1024)
50 x 104857 ~= 5MP
500 x 10485 ~= 5MP
и т.д.
Крупнейшие холсты CQUARE ( "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
Ответ 5
В соответствии с спецификациями w3 интерфейс ширины/высоты является unsigned long - так от 0 до 4,294,967,295 (если я помню, что число справа - может быть от нескольких).
EDIT: Странно, он говорит unsigned long, но это тестирование показывает только нормальное длинное значение как max: 2147483647. Jsfiddle - 47 работает, но до 48 и возвращается к умолчанию.
Ответ 6
Даже если холст позволит вам поставить height = 2147483647, когда вы начнете рисовать, ничего не произойдет
Рисование происходит только тогда, когда я возвращаю высоту до 32767
Ответ 7
iOS имеет разные пределы.
Используя симулятор iOS 7, я смог продемонстрировать, что предел равен 5 Мбайт:
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
Ответ 8
На ПК -
Я не думаю, что есть ограничение, но да, вы можете получить исключение из памяти.
На мобильных устройствах -
Ниже приведены ограничения для холста для мобильных устройств: -
Максимальный размер для элемента canvas - 3 мегапикселя для устройств с объемом памяти менее 256 МБ и 5 мегапикселей для устройств с большей или равной 256 МБ ОЗУ.
Итак, например, если вы хотите поддерживать аппаратное оборудование Apple, размер вашего холста не может превышать 2048 × 1464.
Надеюсь, что эти ресурсы помогут вам вытащить вас.
Ответ 9
Ограничения для Safari (все платформы) значительно ниже.
Известные ограничения iOS/Safari
Например, у меня был буфер холста 6400x6400px с данными, нарисованными на нем. Трассируя/экспортируя контент и тестируя в других браузерах, я смог увидеть, что все в порядке. Но в Safari он пропускает чертеж этого конкретного буфера в мой основной контекст.
Ответ 10
Я попытался программно определить ограничение: установив размер холста, начиная с 35000, уступив 100, пока не будет найден правильный размер. На каждом шаге записывается правый нижний пиксель, а затем читается. Он работает - с осторожностью.
Скорость приемлема, если ширина или высота установлены на некоторое низкое значение (например, 10-200) следующим образом: get_max_canvas_size('height', 20)
.
Но если вызывается без ширины или высоты, например, get_max_canvas_size()
, созданный холст настолько велик, что чтение SINGLE пиксельного цвета происходит очень медленно, а в IE возникает серьезная зависания.
Если подобное испытание может быть выполнено каким-то образом без чтения значения пикселя, скорость будет приемлемой.
Конечно, самым простым способом определения максимального размера был бы собственный способ запроса максимальной ширины и высоты. Но Холст - это "живой стандарт", так может случиться, что он придет в какой-то день.
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
Когда вы используете полотна WebGL, браузеры (включая настольные) будут накладывать дополнительные ограничения на размер нижележащего буфера. Даже если ваш холст большой, например, 16 000 x 16 000, большинство браузеров отрисовывают картинку меньшего размера (скажем, 4096 x 4096) и масштабируют ее. Это может вызвать уродливое пикселирование и т.д.
Я написал некоторый код для определения этого максимального размера с помощью экспоненциального поиска, если кому-то это понадобится. 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/
Ответ 12
Обновление для 2018 года:
С течением времени ограничения холста изменились. К сожалению, что не изменилось, так это то, что браузер по-прежнему не предоставляет информацию об ограничениях размера холста через Canvas API.
Для тех, кто хочет программно определить максимальный размер холста в браузере или протестировать поддержку пользовательских размеров холста, ознакомьтесь с размером холста.
Из документов:
Элемент HTML-холста широко поддерживается современными и устаревшими браузерами, но каждая комбинация браузера и платформы накладывает уникальные ограничения по размеру, что делает холст непригодным для использования при превышении. К сожалению, браузеры не обеспечивают способ определения их ограничений, а также не предоставляют никакой обратной связи после создания непригодного холста. Это затрудняет работу с большими элементами canvas, особенно для приложений, которые поддерживают различные браузеры и платформы.
Эта микробиблиотека предоставляет максимальную площадь, высоту и ширину элемента холста HTML, поддерживаемого браузером, а также возможность проверки пользовательских размеров холста. Собирая эту информацию перед созданием нового элемента canvas, приложения могут надежно устанавливать размеры холста в пределах ограничений размера каждого браузера/платформы.
Демонстрационная ссылка и результаты тестирования доступны в README, а также в разделе об известных проблемах, который затрагивает вопросы производительности и виртуальной машины.
Полное раскрытие, я автор библиотеки. Я создал его в 2014 году и недавно пересмотрел код для нового проекта, связанного с холстом. Я был удивлен, обнаружив то же отсутствие доступных инструментов для определения ограничений размера холста в 2018 году, поэтому я обновил код, выпустил его и надеюсь, что он поможет другим столкнуться с подобными проблемами.
Ответ 13
Вы можете его обрезать, а в javascript автоматически добавить столько маленьких холстов, сколько необходимо, и нарисовать элементы на соответствующем холсте. В конечном итоге у вас может быть нехватка памяти, но вы получите единственный предел холста.
Ответ 14
Я не знаю, как определить максимальный размер без повторения, но вы можете определить, работает ли заданный размер холста, заполнив пиксель, а затем прочитав цвет обратно. Если холст не отображен, тогда цвет, который вы получите, не будет соответствовать. Вт
частичный код:
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);