높이 600
가 1000
픽셀이고 너비가 수만 또는 수십만 픽셀 인 캔버스 요소로 작업하고 있습니다. 그러나 특정 픽셀 수 (분명히 알려지지 않음)가 지나면 캔버스에 JS로 그린 모양이 더 이상 표시되지 않습니다.
제한이 있는지 아는 사람이 있습니까?
Chrome 12 및 Firefox 4에서 모두 테스트되었습니다.
높이 600
가 1000
픽셀이고 너비가 수만 또는 수십만 픽셀 인 캔버스 요소로 작업하고 있습니다. 그러나 특정 픽셀 수 (분명히 알려지지 않음)가 지나면 캔버스에 JS로 그린 모양이 더 이상 표시되지 않습니다.
제한이 있는지 아는 사람이 있습니까?
Chrome 12 및 Firefox 4에서 모두 테스트되었습니다.
답변:
2014 년 10 월 13 일 업데이트 됨
테스트 된 모든 브라우저에는 캔버스 요소의 높이 / 너비에 대한 제한이 있지만 많은 브라우저는 캔버스 요소의 전체 영역도 제한합니다. 테스트 할 수있는 브라우저에 대한 제한은 다음과 같습니다.
최대 높이 / 너비 : 32,767 픽셀
최대 영역 : 268,435,456 픽셀 (예 : 16,384 x 16,384)
최대 높이 / 너비 : 32,767 픽셀
최대 영역 : 472,907,776 픽셀 (예 : 22,528 x 20,992)
최대 높이 / 너비 : 8,192 픽셀
최대 영역 : N / A
최대 높이 / 너비 : 4,096 픽셀
최대 영역 : N / A
지금은 다른 브라우저를 테스트 할 수 없습니다. 추가 제한 사항은이 페이지의 다른 답변을 참조하십시오.
대부분의 브라우저에서 최대 길이 / 너비 / 영역을 초과하면 캔버스를 사용할 수 없게됩니다. (사용 가능한 영역에서도 그리기 명령을 무시합니다.) IE 및 IE Mobile은 사용 가능한 공간 내의 모든 그리기 명령을 준수합니다.
<canvas>
요소 를 사용 하고 적절한 컨텍스트에 자동으로 그리기 지침을 적용 하는 캔버스 API 주위에 래퍼를 작성했습니다 .
캔버스 높이가 8000보다 큰 Firefox에서 메모리 부족 오류가 발생했습니다. 크롬은 최소한 32000까지 훨씬 더 높은 수준으로 처리하는 것 같습니다.
편집 : 더 많은 테스트를 실행 한 후 Firefox 16.0.2에서 매우 이상한 오류를 발견했습니다.
첫째, html 선언 캔버스와 달리 메모리 (자바 스크립트로 생성) 캔버스에서 다른 동작을 얻는 것 같습니다.
둘째, 적절한 html 태그와 메타 문자 세트가 없으면 캔버스가 8196으로 제한 될 수 있으며 그렇지 않으면 32767까지 이동할 수 있습니다.
셋째, 캔버스의 2d 컨텍스트를 얻은 다음 캔버스 크기를 변경하면 8196으로 제한 될 수도 있습니다. 2d 컨텍스트를 잡기 전에 캔버스 크기를 설정하기 만하면 메모리 오류없이 최대 32767을 가질 수 있습니다.
일관되게 메모리 오류를 얻을 수 없었으며 때로는 첫 번째 페이지로드에서만 발생하고 후속 높이 변경이 작동합니다. 이것은 http://pastebin.com/zK8nZxdE 로 테스트 한 html 파일 입니다.
@FredericCharette 답변에 대해 조금 확장하려면 : "iOS 리소스 제한 이해"섹션 아래에있는 safari의 콘텐츠 가이드에 따라 :
캔버스 요소의 최대 크기는 RAM이 256MB 미만인 장치의 경우 3 메가 픽셀이고 RAM이 256MB 이상인 장치의 경우 5 메가 픽셀입니다.
따라서 5242880 (5 x 1024 x 1024) 픽셀의 모든 크기 변형은 대용량 메모리 장치에서 작동하고 그렇지 않으면 3145728 픽셀입니다.
5 메가 픽셀 캔버스의 예 (너비 x 높이) :
Any total <= 5242880
--------------------
5 x 1048576 ~= 5MP (1048576 = 1024 x 1024)
50 x 104857 ~= 5MP
500 x 10485 ~= 5MP
등등..
가장 큰 SQUARE 캔버스는 ( "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
2018 년 업데이트 :
시간이 지남에 따라 캔버스 제한이 변경되었습니다. 안타깝게도 변경되지 않은 것은 브라우저가 여전히 Canvas API를 통해 캔버스 크기 제한에 대한 정보를 제공하지 않는다는 사실입니다.
프로그래밍 방식으로 브라우저의 최대 캔버스 크기를 결정하거나 사용자 정의 캔버스 크기에 대한 지원을 테스트하려는 경우 canvas-size를 확인하십시오 .
문서에서 :
HTML 캔버스 요소는 최신 및 레거시 브라우저에서 널리 지원되지만 각 브라우저 및 플랫폼 조합은 초과시 캔버스를 사용할 수 없게 만드는 고유 한 크기 제한을 부과합니다. 안타깝게도 브라우저는 제한 사항을 확인할 수있는 방법을 제공하지 않으며 사용할 수없는 캔버스가 생성 된 후 어떤 종류의 피드백도 제공하지 않습니다. 따라서 특히 다양한 브라우저와 플랫폼을 지원하는 응용 프로그램의 경우 큰 캔버스 요소로 작업하는 것이 어렵습니다.
이 마이크로 라이브러리는 브라우저에서 지원하는 HTML 캔버스 요소의 최대 영역, 높이 및 너비와 사용자 정의 캔버스 크기를 테스트하는 기능을 제공합니다. 새 캔버스 요소가 생성되기 전에이 정보를 수집함으로써 애플리케이션은 각 브라우저 / 플랫폼의 크기 제한 내에서 캔버스 크기를 안정적으로 설정할 수 있습니다.
데모 링크 및 테스트 결과는 에서 사용할 수있는 README 뿐만 아니라 알려진 문제 성능 및 가상 머신 고려 사항에 닿는 부분.
전체 공개, 나는 도서관의 저자입니다. 2014 년에 다시 만들었고 최근에 새로운 캔버스 관련 프로젝트의 코드를 다시 검토했습니다. 2018 년에 캔버스 크기 제한을 감지하는 데 사용할 수있는 도구가 똑같이 부족하다는 사실에 놀랐 기 때문에 코드를 업데이트하고 릴리스했으며 다른 사람들이 유사한 문제를 겪는 데 도움이되기를 바랍니다.
w3 사양 에 따르면 너비 / 높이 인터페이스는 부호없는 길이이므로 0에서 4,294,967,295까지입니다 (그 숫자를 기억한다면-약간 떨어져있을 수 있습니다).
편집 : 이상하게도 unsigned long이라고 말하지만 테스트는 최대 길이 인 2147483647로 정상 long 값만 표시합니다. Jsfiddle -47은 작동하지만 최대 48 개이며 기본값으로 돌아갑니다.
캔버스에서 height = 2147483647을 입력 할 수 있지만 그리기를 시작하면 아무 일도 일어나지 않습니다.
드로잉은 높이를 32767로 되돌릴 때만 발생합니다.
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
Safari (모든 플랫폼)에 대한 제한은 훨씬 낮습니다.
예를 들어, 데이터가 그려진 6400x6400px 캔버스 버퍼가 있습니다. 콘텐츠를 추적 / 내 보낸 다음 다른 브라우저에서 테스트하여 모든 것이 정상임을 확인할 수있었습니다. 그러나 Safari에서는이 특정 버퍼의 그리기를 내 주요 컨텍스트로 건너 뜁니다.
저는 프로그래밍 방식으로 한계를 알아 내려고했습니다. 캔버스 크기를 35000에서 시작하여 유효한 크기를 찾을 때까지 100 씩 줄였습니다. 모든 단계에서 오른쪽 하단 픽셀을 쓰고 읽습니다. 조심스럽게 작동합니다.
너비 또는 높이가 다음과 같이 낮은 값 (예 : 10-200)으로 설정된 경우 속도가 허용됩니다 get_max_canvas_size('height', 20)
.
그러나 너비 나 높이없이 호출 get_max_canvas_size()
하면 생성 된 캔버스가 너무 커서 단일 픽셀 색상을 읽는 것이 매우 느리고 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;
}
}
WebGL 캔버스를 사용하는 경우 브라우저 (데스크톱 포함)는 기본 버퍼의 크기에 추가 제한을 부과합니다. 캔버스가 16,000x16,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/
당신은 그것을 청크하고 자바 스크립트에서 필요한만큼 작은 캔버스를 자동으로 추가하고 적절한 캔버스에 요소를 그릴 수 있습니다. 결국에는 여전히 메모리가 부족할 수 있지만 단일 캔버스 제한으로 인해 발생합니다.
나는 itteration없이 가능한 최대 크기를 감지하는 방법을 모르지만 주어진 캔버스 크기가 픽셀을 채운 다음 색상을 다시 읽어서 작동하는지 감지 할 수 있습니다. 캔버스가 렌더링되지 않은 경우 반환되는 색상이 일치하지 않습니다. 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);
tens OR hundreds of thousands
...