私は、高さcanvas要素で働いている600
の1000
ピクセルとピクセル数万あるいは数百の幅。ただし、一定数のピクセル(明らかに不明)の後、キャンバスにJSで描画した形状が表示されなくなります。
制限があるかどうか誰か知っていますか?
Chrome 12とFirefox 4の両方でテスト済み。
私は、高さcanvas要素で働いている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ピクセル
最大面積:該当なし
最大の高さ/幅:4,096ピクセル
最大領域:該当なし
現在、他のブラウザをテストすることはできません。その他の制限については、このページの他の回答を参照してください。
ほとんどのブラウザで最大長/幅/面積を超えると、キャンバスが使用できなくなります。(使用可能な領域でも、描画コマンドは無視されます。)IEおよびIE Mobileは、使用可能なスペース内のすべての描画コマンドを受け入れます。
<canvas>
要素を使用し、適切なコンテキストに描画命令を自動的に適用するcanvas APIのラッパーを作成することになりました。
キャンバスの高さが8000を超えるFirefoxでメモリ不足エラーに遭遇しました。Chromeは、少なくとも32000まで、はるかに高い値を処理するようです。
編集:さらにいくつかのテストを実行した後、Firefox 16.0.2でいくつかの非常に奇妙なエラーを見つけました。
まず、htmlで宣言されたキャンバスとは異なり、メモリ内(JavaScriptで作成)のキャンバスとは異なる動作をするようです。
次に、適切なhtmlタグとメタ文字セットがない場合、キャンバスは8196に制限される可能性があります。それ以外の場合は、32767まで設定できます。
3番目に、キャンバスの2Dコンテキストを取得してからキャンバスサイズを変更すると、8196に制限される可能性があります。2Dコンテキストを取得する前にキャンバスサイズを設定するだけで、メモリエラーが発生することなく最大32767を使用できます。
一貫してメモリエラーを取得できませんでした。最初のページの読み込み時だけに発生することがあり、その後の高さの変更が機能します。これは、http://pastebin.com/zK8nZxdEでテストしていたhtmlファイルです。
@FredericCharetteの回答を少し拡張するには:「iOSリソースの制限について」セクションのサファリのコンテンツガイドに従って:
canvas要素の最大サイズは、RAMが256 MB未満のデバイスでは3メガピクセル、RAMが256 MB以上のデバイスでは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のcanvas要素は、最新のブラウザーとレガシーブラウザーで広くサポートされていますが、ブラウザーとプラットフォームの組み合わせごとに固有のサイズ制限があり、超過するとキャンバスが使用できなくなります。残念ながら、ブラウザーは、制限が何であるかを判別する方法を提供していません。また、使用できないキャンバスが作成された後に、フィードバックを提供していません。このため、特にさまざまなブラウザやプラットフォームをサポートするアプリケーションでは、大きなキャンバス要素の操作が困難になります。
このマイクロライブラリは、ブラウザでサポートされているHTMLキャンバス要素の最大領域、高さ、および幅を提供し、カスタムキャンバスのサイズをテストする機能を提供します。新しいcanvas要素が作成される前にこの情報を収集することにより、アプリケーションは、各ブラウザー/プラットフォームのサイズ制限内でキャンバスのサイズを確実に設定できます。
デモリンクとテスト結果は、READMEで入手できます。また、パフォーマンスと仮想マシンの考慮事項について説明している既知の問題のセクションもあります。
完全な開示、私は図書館の著者です。私は2014年にそれを作成し、最近、新しいキャンバス関連プロジェクトのコードを再検討しました。2018年にキャンバスサイズの制限を検出するために利用できるツールが同じように不足していることに驚いたので、コードを更新してリリースし、他の人が同様の問題に遭遇するのを助けることを願っています。
w3仕様によると、幅/高さのインターフェイスは符号なしlongなので、0から4,294,967,295までです(その数値を覚えていれば-少しずれているかもしれません)。
EDIT:不思議、それはunsigned long型と言うが、それは最高のように普通のlong値のショーをテスト:2147483647 Jsfiddle - 48に47点の作品が、アップと、それはデフォルトの値に戻ります。
キャンバスでは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
しかし、キャンバスサイズを1行のピクセルだけナッジすると、次のようになります。
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()
、作成されたキャンバスは非常に大きくなるため、1ピクセルの色の読み取りが非常に遅くなり、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;
}
}
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/
それをチャンクにして、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);
tens OR hundreds of thousands
...