HTML5 <canvas> 'ın desteklenmediğini tespit etmenin en iyi yolu


139

Tarayıcının HTML5 <canvas>etiketini desteklemediği durumlarla başa çıkmanın standart yolu , aşağıdakiler gibi bazı yedek içerikleri yerleştirmektir:

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

Ancak sayfanın geri kalanı aynı kalır, bu uygunsuz veya yanıltıcı olabilir. Tuvalimin desteklenmediğini tespit etmenin bir yolunu istiyorum, böylece sayfamın geri kalanını buna göre sunabilirim. Ne önerirsiniz?

Yanıtlar:


217

Modernizr'de ve temelde tuval çalışması yapan diğer tüm kütüphanelerde kullanılan teknik budur:

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

O ne zaman soru tespiti için olduğu için değil desteklenen, ben şöyle kullanıyorum tavsiye:

if (!isCanvasSupported()){ ...

14
Çifte olumsuzluk (!!) neden duruyor?

16
Tuval orada değilse elem.getContext == undefined. !undefined = trueve !true = falseböylece tanımsız veya bağlam yerine bir bool döndürmemize izin verir.
Zengin Bradshaw

1
@ 2astalavista Çift negatif (!!) döküm gibidir. Truey veya falsey ifadesini bir boole'ye dönüştürür. Örneğin: var i = 0. i yanlış olarak değerlendirir, ancak typeof i "sayı" döndürür. typeof !! i "boolean" döndürür.
Kullanıcı2

Boole'ye "döküm" yapmanın başka bir yolu da: undefined ? true : false(biraz daha uzun olsa da).
vcapra1

1
Farklı tuval desteği türleri olduğu unutulmamalıdır. Erken tarayıcı uygulamaları desteklenmedi toDataURL. Opera Mini yalnızca metin API desteği olmadan temel tuval oluşturmayı destekler . Opera Mini , sadece çapraz referans için bu şekilde hariç tutulabilir .
hexalys

103

Tarayıcılarda tuval desteğini tespit etmenin iki popüler yöntemi vardır:

  1. Matt'in varlığını kontrol etme önerisigetContext , Modernizr kütüphanesi tarafından da benzer şekilde kullanılır:

    var canvasSupported = !!document.createElement("canvas").getContext;
  2. WebIDL ve HTML spesifikasyonları HTMLCanvasElementtarafından tanımlanan arayüzün varlığını kontrol etme . Bu yaklaşım IE 9 ekibinin bir blog yazısında da önerildi .

    var canvasSupported = !!window.HTMLCanvasElement;

Benim tavsiyem, birkaç nedenden dolayı ikincisinin bir çeşididir ( Ek Notlara bakın ):

  • IE 9 dahil olmak üzere kanvas destekleyen her bilinen tarayıcı bu arayüzü uygular;
  • Kodun ne yaptığına dair daha özlü ve anında açıktır;
  • getContextYaklaşımdır önemli ölçüde yavaş tüm tarayıcılarda bir HTML elemanı oluşturma içerir çünkü. Mümkün olduğunca fazla performans sıkıştırmanız gerektiğinde bu ideal değildir (örneğin Modernizr gibi bir kütüphanede).

İlk yöntemi kullanmanın belirgin bir faydası yoktur. Her iki yaklaşım da taklit edilebilir, ancak bunun kazara olması muhtemel değildir.

ek Notlar

Yine de bir 2D içeriğin alınabildiğini kontrol etmek gerekebilir. Habere göre, bazı mobil tarayıcılar çeklerin üzerindeki her ikisi için return true, ancak dönebilir nulliçin .getContext('2d'). Modernizr'in de sonucunu kontrol etmesinin nedeni budur .getContext('2d'). Ancak, WebIDL ve HTML - yine - bize daha iyi, daha hızlı bir seçenek sunar:

var canvas2DSupported = !!window.CanvasRenderingContext2D;

Tuval öğesini kontrol etmeyi tamamen atlayabileceğimize ve doğrudan 2B oluşturma desteğini kontrol etmeye gidebileceğimize dikkat edin. CanvasRenderingContext2DArayüz ayrıca HTML şartnamenin parçasıdır.

Sen gerekir kullanmak getContextyaklaşımı WebGL tespit etmek için tarayıcının destekleyebileceği bile, çünkü destek WebGLRenderingContext, getContext()döndürebilir null adlı tarayıcı nedeniyle sürücü sorunları GPU ile arayüz edemiyor ve hiçbir yazılım uygulaması varsa. Bu durumda, arabirimi kontrol etmek önce şunları kontrol etmenizi atlamanızı sağlar 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
    }
}

Performans karşılaştırması

getContextFirefox 11 ve Opera 11'de yaklaşımın performansı % 85-90 daha yavaş ve Chromium 18'de yaklaşık% 55 daha yavaş.

    Basit karşılaştırma tablosu, tarayıcınızda bir test çalıştırmak için tıklayın


10
Nokia S60 ve Blackberry Storm, önerilen 2B tuval algılamanızda yanlış pozitif çıkacak bazı cihazlar arasında. Ne yazık ki, mobil cihazlar çok kıllı oluyor ve satıcılar kurallara uymuyor. :( Doğru sonuçları elde etmek için daha eksiksiz (yani daha yavaş) testler yapıyoruz
Paul Irish

@Paul: Bu ilginç, BlackBerry Storm emülatörlerini test ettim, hepsi falsehem örnek hem de benim için döndü , CanvasRenderingContext2Darayüz sağlamazlar gibi görünüyor . S60'ı henüz test edemedim, hala çok merak ediyorum ve yakında yapabilirim.
Andy E

1
Bu ilginç, ama test yüz milin altında gerçekleştiği sürece, bu iyi değil mi? Zaten bunların hepsinden çok daha hızlı olduklarını hayal ediyorum. Bunu test eden bir işlevi hatırlarsanız, maliyeti yalnızca bir kez ödemeniz gerekir.
Drew Noakes

1
Kıyasınızı çalıştırdım ve 'yavaş' yaklaşım bile saniyede ~ 800.000 kez yapılabilir. Yine, sonuç önbelleğe alınırsa, hangi yaklaşımın kullanılacağı kararı performansa değil, sağlamlığa dayanmalıdır (sağlamlıkta bir fark olduğu varsayılarak)
Drew Noakes

@DrewNoakes: evet, neredeyse her zaman hız üzerinde uyumluluk için gitmelisiniz. Benim iddiam, Paul'ün uyumluluk iddialarını, yorumunda bahsettiği sorun tarayıcılarından en az birinde yaptığım testlere dayanarak reddettiğim. Diğer tarayıcıyı test edemedim ama bir sorun olduğundan emin değilim. Uyumluluktan ödün vermeden daima mümkün olan en iyi performansı almayı hedeflemelisiniz. Mikro optimizasyondan bahsetmiyorum, ancak yüzlerce test yapıyorsanız ve hepsi optimize edilmemişse, evet, bir fark yaratabilir.
Andy E

13

getContextTuval nesnesimi oluşturduğumda genellikle bir denetim çalıştırırım .

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

Destekleniyorsa, tuval kurulumuna devam edebilir ve DOM'a ekleyebilirsiniz. Bu, Zarif Degradasyon yerine (kişisel olarak) tercih ettiğim Progressive Enhancement'a basit bir örnektir .


Bu , contextikinci çizgide başıboş mı ?
brainjam

7
@brainjam - Hayır, bu değişkeni kodun sonuna yaklaşıyorum. Ben JSLint 'önerileri' (bu durumda .. varher işlev için sadece 1 ifade) takip etmeye çalışın .
Matt

6

Neden modernizr'i denemiyorsunuz ? Algılama yeteneği sağlayan bir JS kütüphanesi.

Alıntı:

Sınır yarıçapı gibi harika özelliklerin kullanılabilirliği için CSS'nizde if-ifadeleri yapmak istediniz mi? Modernizr ile bunu başarabilirsiniz!


2
Modernizr'de kullandığımız test şudur: return !!document.createElement('canvas').getContext Bu kesinlikle test etmenin en iyi yoludur.
Paul Irish

4
Modernizr yararlı bir kütüphanedir, ancak sadece tuval desteğini tespit etmek için tüm kütüphaneyi çekmek biraz boşa gidecektir. Diğer özellikleri de tespit etmeniz gerekiyorsa, bunu tavsiye ederim.
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.");
}

1

Burada bir gotcha olabilir - bazı müşteriler tüm tuval yöntemlerini desteklemez .

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

Tarayıcılarınızın tuvali destekleyip desteklemediğini tespit etmek için canisuse.js komut dosyasını kullanabilirsiniz

caniuse.canvas()

0

Tuvalinizin bağlamını elde edecekseniz, bunu test olarak da kullanabilirsiniz:

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 :(*/
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.