HTML5 <canvas>がサポートされていないことを検出する最良の方法


139

ブラウザがHTML5 <canvas>タグをサポートしない状況に対処する標準的な方法は、次のようなフォールバックコンテンツを埋め込むことです。

<canvas>Your browser doesn't support "canvas".</canvas>

ただし、ページの残りの部分は同じままで、不適切または誤解を招く可能性があります。キャンバスの非サポートを検出して、残りのページを適切に表示できるようにしたいのですが。あなたは何をお勧めします?

回答:


217

これは、Modernizrで使用されている手法であり、基本的にはキャンバスで機能する他のすべてのライブラリです。

function isCanvasSupported(){
  var elem = document.createElement('canvas');
  return !!(elem.getContext && elem.getContext('2d'));
}

あなたの質問はサポートされていない場合の検出に関するものだったので、次のように使用することをお勧めします。

if (!isCanvasSupported()){ ...

14
二重否定(!!)はなぜですか?

16
キャンバスがない場合は、elem.getContext == undefined!undefined = true、および!true = false、これにより、未定義またはコンテキストではなく、ブール値を返すことができます。
リッチブラッドショー

1
@ 2astalavistaダブルネガティブ(!!)はキャストのようなものです。これは、trueまたはfalseのステートメントをブール値に変換します。例:var i = 0。iはfalseと評価されますが、typeof iは「number」を返します。typeof !! iは「boolean」を返します。
User2 14年

ブール値に「キャスト」するもう1つの方法は次のとおりですundefined ? true : false(ただし、少し長くなります)。
vcapra1 2014

1
キャンバスのサポートにはさまざまなタイプがあることに注意してください。初期のブラウザ実装では、はサポートされていませんでしたtoDataURL。また、Opera Miniは基本的なキャンバスレンダリングのみをサポートし、テキストAPIはサポートしていません。Opera Miniは、相互参照のために、この方法で除外できます。
hexalys 2016年

103

ブラウザでのキャンバスのサポートを検出するには、2つの一般的な方法があります。

  1. の存在をチェックするというマットの提案getContext。Modernizrライブラリでも同様に使用されます。

    var canvasSupported = !!document.createElement("canvas").getContext;
  2. WebIDLおよびHTML仕様でHTMLCanvasElement定義されている、インターフェースの存在の確認。このアプローチは、IE 9チームのブログ投稿でも推奨されていまし

    var canvasSupported = !!window.HTMLCanvasElement;

私の推奨は、いくつかの理由により、後者のバリエーションです(「追加情報」を参照)。

  • キャンバスをサポートするすべての既知のブラウザー(IE 9を含む)がこのインターフェースを実装しています。
  • コードが何をしているかがより簡潔で即座にわかります。
  • このgetContext方法では、HTML要素の作成が含まれるため、すべてのブラウザ速度大幅に低下します。これは、(たとえば、Modernizrなどのライブラリで)可能な限り多くのパフォーマンスを絞る必要がある場合には理想的ではありません。

最初の方法を使用しても目立った利点はありません。どちらの方法も偽装される可能性がありますが、これは偶然に起こることはまずありません。

その他の注意事項

2Dコンテキストを取得できることを確認する必要がある場合があります。報道によると、一部のモバイルブラウザは、上記の両方のチェックのためにtrueを返しますが、返すことができるnullため.getContext('2d')。これが、Modernizrがの結果もチェックする理由です.getContext('2d')。ただし、WebIDLとHTMLは、再び、より優れた高速なオプションを提供します。

var canvas2DSupported = !!window.CanvasRenderingContext2D;

canvas要素のチェックを完全にスキップして、2Dレンダリングサポートのチェックに直接進むことができることに注意してください。CanvasRenderingContext2Dインターフェースはまた、HTML仕様の一部です。

あなたは必要があります使用しgetContextたアプローチのWebGL検出するためのブラウザがサポートしている場合でも、ためのサポートをWebGLRenderingContextgetContext()返すことがヌルのブラウザが原因ドライバの問題にGPUとのインタフェースすることができず、何のソフトウェア実装がない場合。この場合、最初にインターフェースを確認すると、次の確認をスキップできますgetContext

var cvsEl, ctx;
if (!window.WebGLRenderingContext)
    window.location = "http://get.webgl.org";
else {
    cvsEl = document.createElement("canvas");
    ctx = cvsEl.getContext("webgl") || cvsEl.getContext("experimental-webgl");

    if (!ctx) {
        // Browser supports WebGL, but cannot create the context
    }
}

性能比較

このgetContextアプローチのパフォーマンスは、Firefox 11とOpera 11では85〜90%遅く、Chromium 18では約55%遅くなっています。

    簡単な比較表、クリックしてブラウザーでテストを実行


10
Nokia S60とBlackberry Stormは、提案された2Dキャンバス検出で誤検知を起こすデバイスの一部です。残念ながら、モバイルは非常に厄介で、ベンダーはルールに従っていません。:(正確な結果を保証するために(すなわち遅い)のテストより完全に終わる我々はそう。
ポール・アイリッシュ

@Paul:興味深いですね。BlackBerryStormエミュレータをテストしました。すべてのfalse例と私の両方に返されましたが、CanvasRenderingContext2Dインターフェースを提供していないようです。私はまだS60をテストすることができませんでした、しかし私はまだ非常に好奇心が強く、すぐにそうするかもしれません。
アンディE

1
これはおもしろいですが、テストが100ミリ程度で行われる限り、それで問題ありませんか?とにかく、それらはすべてそれよりもはるかに速いと思います。これをテストする関数を覚えている場合は、コストを1回支払うだけで済みます。
Drew Noakes 2013年

1
私はあなたのベンチマークを実行しました、そして「遅い」アプローチでさえ毎秒約800,000回行うことができます。繰り返しになりますが、結果がキャッシュされる場合、使用するアプローチの決定は、パフォーマンスではなくロバスト性に基づく必要があります(ロバスト性に違いがあると想定しています)
Drew Noakes

@DrewNoakes:はい、速度よりも互換性を保つために、ほとんどの場合は移動する必要があります。私の主張は、彼がコメントで言及した問題のあるブラウザーの少なくとも1つでの私自身のテストに基づいて、ポールによる互換性の主張に反論しているということです。他のブラウザをテストすることはできませんでしたが、問題があることに確信が持てません。互換性を犠牲にすることなく、常に可能な限り最高のパフォーマンスを得ることを目指してください。私はマイクロ最適化について話しているわけではありませんが、何百ものテストを実行していて、それらすべてが最適化されていない場合、そうです、違いを生む可能性があります。
アンディE

13

私は通常getContext、キャンバスオブジェクトを作成するときにチェックを実行します。

(function () {
    var canvas = document.createElement('canvas'), context;
    if (!canvas.getContext) {
        // not supported
        return;
    }

    canvas.width = 800;
    canvas.height = 600;
    context = canvas.getContext('2d');
    document.body.appendChild(canvas);
}());

サポートされている場合は、キャンバスのセットアップを続行してDOMに追加できます。これはProgressive Enhancementの簡単な例であり、私は(個人的に)Graceful Degradationよりも優先しています。


それは, context2行目の迷いですか?
ブレインジャム2010

7
@brainjam-いいえ、コードの終わり近くでその変数を使用しています。JSLintの「推奨事項」に従うようにしています(この場合varは、関数ごとに1つのステートメントのみ)。
マット

6

modernizrを試してみませんか?これは、検出機能を提供するJSライブラリです。

見積もり:

border-radiusのようなクールな機能を利用できるようにするために、CSSでifステートメントを実行したいと思ったことはありませんか?まあ、Modernizrを使えば、まさにそれを達成できます!


2
modernizrで使用するテストは次のとおりです。return !!document.createElement('canvas').getContext これが間違いなくテストする最良の方法です。
ポールアイルランド

4
Modernizrは便利なライブラリですが、キャンバスのサポートを検出するためだけにライブラリ全体を取り込むのは少し無駄です。他の機能も検出する必要がある場合は、お勧めします。
ダニエルキャシディ

5
try {
    document.createElement("canvas").getContext("2d");
    alert("HTML5 Canvas is supported in your browser.");
} catch (e) {
    alert("HTML5 Canvas is not supported in your browser.");
}

1

ここで落とし穴があるかもしれません-一部のクライアントはすべてのキャンバスメソッドをサポートしていません。

var hascanvas= (function(){
    var dc= document.createElement('canvas');
    if(!dc.getContext) return 0;
    var c= dc.getContext('2d');
    return typeof c.fillText== 'function'? 2: 1;
})();

alert(hascanvas)

0

canisuse.jsスクリプトを使用して、ブラウザーがキャンバスをサポートしているかどうかを検出できます

caniuse.canvas()

0

キャンバスのコンテキストを取得する場合は、それをテストとして使用することもできます。

var canvas = document.getElementById('canvas');
var context = (canvas.getContext?canvas.getContext('2d'):undefined);
if(!!context){
  /*some code goes here, and you can use 'context', it is already defined*/
}else{
  /*oof, no canvas support :(*/
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.