Der beste Weg, um festzustellen, dass HTML5 <canvas> nicht unterstützt wird

139

Die Standardmethode für Situationen, in denen der Browser das HTML5- <canvas>Tag nicht unterstützt, besteht darin, einige Fallback-Inhalte einzubetten, z.

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

Der Rest der Seite bleibt jedoch derselbe, was unangemessen oder irreführend sein kann. Ich möchte eine Möglichkeit erkennen, nicht unterstützte Zeichenflächen zu erkennen, damit ich den Rest meiner Seite entsprechend präsentieren kann. Was würden Sie empfehlen?

Brainjam
quelle

Antworten:

217

Dies ist die Technik, die in Modernizr und im Grunde jeder anderen Bibliothek verwendet wird, die Leinwandarbeit leistet:

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

Da Ihre Frage zur Erkennung diente, wenn sie nicht unterstützt wird, empfehle ich, sie folgendermaßen zu verwenden:

if (!isCanvasSupported()){ ...
Paul Irish
quelle
14
Warum steht die doppelte Negation (!!) für?
16
Wenn Canvas nicht da ist , elem.getContext == undefined. !undefined = true, und !true = false, so können wir einen Bool zurückgeben, anstatt undefiniert oder den Kontext.
Rich Bradshaw
1
@ 2astalavista Das Doppel-Negativ (!!) ist wie Casting. Es verwandelt eine wahre oder falsche Aussage in einen Booleschen. Zum Beispiel : var i = 0. Ich werte mit false aus, aber typeof i gibt "number" zurück. typeof !! Ich gebe "boolean" zurück.
User2
Eine andere Möglichkeit, Boolesche Werte zu "umwandeln", ist: undefined ? true : false(wenn auch etwas länger).
vcapra1
1
Ich sollte beachten, dass es verschiedene Arten der Leinwandunterstützung gibt. Frühere Browser-Implementierungen wurden nicht unterstützt toDataURL. Und Opera Mini unterstützt nur einfaches Canvas-Rendering ohne Unterstützung der Text-API . Opera Mini kann auf diese Weise nur als Querverweis ausgeschlossen werden.
Hexalys
103

Es gibt zwei beliebte Methoden zum Erkennen der Canvas-Unterstützung in Browsern:

  1. Matts Vorschlag , die Existenz von zu überprüfen getContext, wird ebenfalls in ähnlicher Weise von der Modernizr-Bibliothek verwendet:

    var canvasSupported = !!document.createElement("canvas").getContext;
  2. Überprüfen der Existenz der HTMLCanvasElementSchnittstelle, wie in den WebIDL- und HTML- Spezifikationen definiert. Dieser Ansatz wurde auch in einem Blogbeitrag des IE 9-Teams empfohlen .

    var canvasSupported = !!window.HTMLCanvasElement;

Meine Empfehlung ist aus mehreren Gründen eine Variation der letzteren (siehe Zusätzliche Hinweise ):

  • Jeder bekannte Browser, der Canvas unterstützt - einschließlich IE 9 - implementiert diese Schnittstelle.
  • Es ist prägnanter und sofort klar, was der Code tut.
  • Der getContextAnsatz ist in allen Browsern erheblich langsamer , da ein HTML-Element erstellt wird. Dies ist nicht ideal, wenn Sie so viel Leistung wie möglich erzielen möchten (z. B. in einer Bibliothek wie Modernizr).

Die Verwendung der ersten Methode bietet keine nennenswerten Vorteile. Beide Ansätze können gefälscht werden, dies ist jedoch nicht zufällig.

Zusätzliche Bemerkungen

Möglicherweise muss noch überprüft werden, ob ein 2D-Kontext abgerufen werden kann. Berichten zufolge können einige mobile Browser für beide oben genannten Prüfungen true zurück, aber Rückkehr nullzu .getContext('2d'). Deshalb prüft Modernizr auch das Ergebnis von .getContext('2d'). WebIDL & HTML bietet uns jedoch erneut eine bessere und schnellere Option:

var canvas2DSupported = !!window.CanvasRenderingContext2D;

Beachten Sie, dass wir die Überprüfung des Canvas-Elements vollständig überspringen und direkt zur Überprüfung der Unterstützung für 2D-Rendering übergehen können. Die CanvasRenderingContext2DSchnittstelle ist auch Teil der HTML-Spezifikation.

Sie müssen den getContextAnsatz zum Erkennen der WebGL- Unterstützung verwenden, da der Browser, obwohl er die unterstützt WebGLRenderingContext, getContext()möglicherweise null zurückgibt, wenn der Browser aufgrund von Treiberproblemen keine Schnittstelle zur GPU herstellen kann und keine Softwareimplementierung vorliegt. In diesem Fall können Sie bei der ersten Überprüfung der Schnittstelle die Überprüfung überspringen 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
    }
}

Leistungsvergleich

Die Leistung des getContextAnsatzes ist in Firefox 11 und Opera 11 um 85-90% langsamer und in Chromium 18 um etwa 55% langsamer.

    Klicken Sie auf eine einfache Vergleichstabelle, um einen Test in Ihrem Browser auszuführen

Andy E.
quelle
10
Das Nokia S60 und das Blackberry Storm gehören zu den Geräten, die auf Ihrer vorgeschlagenen 2D-Leinwanderkennung falsch positiv sind. Leider wird das Handy sehr haarig und die Anbieter befolgen keine Regeln. :( Also haben wir am Ende vollständigere (dh langsamere) Tests, um genaue Ergebnisse zu gewährleisten.
Paul Irish
@Paul: Das ist interessant, ich habe die BlackBerry Storm-Emulatoren getestet. Alle wurden falsesowohl für Ihr als auch für mein Beispiel zurückgegeben. Es scheint, dass sie die CanvasRenderingContext2DSchnittstelle nicht bereitstellen . Ich konnte den S60 noch nicht testen, bin aber immer noch sehr neugierig und werde es vielleicht bald tun.
Andy E
1
Das ist interessant, aber solange der Test unter hundert Millis liegt, ist das nicht in Ordnung? Ich stelle mir vor, dass sie sowieso alle viel schneller sind. Wenn Sie sich eine Funktion merken, die dies testet, müssen Sie die Kosten nur einmal bezahlen.
Drew Noakes
1
Ich habe Ihren Benchmark durchgeführt und sogar der "langsame" Ansatz kann ca. 800.000 Mal pro Sekunde durchgeführt werden. Wenn das Ergebnis zwischengespeichert wird, sollte die Entscheidung, welcher Ansatz verwendet werden soll, auf Robustheit und nicht auf Leistung basieren (vorausgesetzt, es gibt einen Unterschied in der Robustheit)
Drew Noakes,
@DrewNoakes: Ja, Sie sollten fast immer Kompatibilität über Geschwindigkeit anstreben. Mein Argument ist, dass ich die Kompatibilitätsansprüche von Paul aufgrund meiner eigenen Tests in mindestens einem der in seinem Kommentar erwähnten Problembrowser widerlege. Ich konnte den anderen Browser nicht testen, bin jedoch nicht davon überzeugt, dass ein Problem vorliegt. Sie sollten immer versuchen, die bestmögliche Leistung zu erzielen, ohne die Kompatibilität zu beeinträchtigen. Ich spreche nicht von Mikrooptimierung, aber wenn Sie Hunderte von Tests durchführen und alle nicht optimiert sind, kann dies einen Unterschied machen.
Andy E
13

Normalerweise überprüfe getContextich, wann ich mein Canvas-Objekt erstelle.

(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);
}());

Wenn dies unterstützt wird, können Sie das Canvas-Setup fortsetzen und dem DOM hinzufügen. Dies ist ein einfaches Beispiel für progressive Verbesserung , das ich (persönlich) Graceful Degradation vorziehe.

Matt
quelle
Ist das ein Streuner , contextin der zweiten Zeile?
Brainjam
7
@brainjam - Nein, ich benutze diese Variable am Ende des Codes. Ich versuche, den JSLint -Empfehlungen zu folgen (in diesem Fall nur 1 varAnweisung pro Funktion).
Matt
6

Warum nicht Modernizr ausprobieren ? Es ist eine JS-Bibliothek, die Erkennungsfunktionen bietet.

Zitat:

Wollten Sie schon immer if-Anweisungen in Ihrem CSS machen, um coole Funktionen wie den Randradius zu erhalten? Mit Modernizr können Sie genau das erreichen!

Frozenskys
quelle
2
Der Test, den wir in modernizr verwenden, ist folgender: return !!document.createElement('canvas').getContext Das ist definitiv der beste Weg, um zu testen.
Paul Irish
4
Modernizr ist eine nützliche Bibliothek, aber es wäre eine Verschwendung, die gesamte Bibliothek abzurufen, um die Canvas-Unterstützung zu erkennen. Wenn Sie auch andere Funktionen erkennen müssen, würde ich es empfehlen.
Daniel Cassidy
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.");
}
Scheich Ali
quelle
1

Möglicherweise liegt hier ein Problem vor - einige Clients unterstützen nicht alle Canvas-Methoden.

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)
kennebec
quelle
0

Wenn Sie den Kontext Ihrer Leinwand erhalten möchten, können Sie ihn genauso gut als Test verwenden:

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 :(*/
}
Callum Hynes
quelle