【问题标题】:Best way to detect that HTML5 <canvas> is not supported检测不支持 HTML5 <canvas> 的最佳方法
【发布时间】:2011-02-14 06:48:31
【问题描述】:

处理浏览器不支持 HTML5 &lt;canvas&gt; 标签的情况的标准方法是嵌入一些后备内容,例如:

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

但页面的其余部分保持不变,这可能不恰当或具有误导性。我想要一些检测画布不支持的方法,以便我可以相应地展示我的页面的其余部分。你会推荐什么?

【问题讨论】:

    标签: javascript html canvas progressive-enhancement graceful-degradation


    【解决方案1】:

    这是 Modernizr 中使用的技术,基本上所有其他可以使用画布的库:

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

    由于您的问题是在支持时进行检测,因此我建议您像这样使用它:

    if (!isCanvasSupported()){ ...
    

    【讨论】:

    • 为什么双重否定(!!)代表?
    • 如果 Canvas 不存在,elem.getContext == undefined!undefined = true!true = false,所以这让我们返回一个布尔值,而不是未定义或上下文。
    • @2astalavista 双重否定(!!)就像铸造。它将 true 或 false 语句转换为布尔值。例如:var i = 0。 i 计算结果为 false,但 typeof i 返回“数字”。 typeof !!i 返回“布尔值”。
    • 另一种“转换”为布尔值的方法是:undefined ? true : false(虽然有点长)。
    • 我应该注意到有不同类型的画布支持。早期的浏览器实现不支持toDataURL。并且 Opera Mini 仅支持 no text API support 的基本画布渲染。 Opera Mini 可以排除this way,仅供参考。
    【解决方案2】:

    在浏览器中检测画布支持有两种流行的方法:

    1. Matt's suggestion 检查getContext 的存在,Modernizr 库也以类似的方式使用:

      var canvasSupported = !!document.createElement("canvas").getContext;
      
    2. 检查HTMLCanvasElement 接口是否存在,由WebIDLHTML 规范定义。 a blog post from the IE 9 team 也推荐了这种方法。

      var canvasSupported = !!window.HTMLCanvasElement;
      

    我的建议是后者的变体(请参阅附加说明),原因如下:

    • 所有支持画布的已知浏览器(包括 IE 9)都实现了此接口;
    • 代码在做什么更简洁明了;
    • getContext 方法是significantly slower across all browsers,因为它涉及创建 HTML 元素。当您需要尽可能多地压缩性能时(例如在 Modernizr 等库中),这并不理想。

    使用第一种方法没有明显的好处。这两种方法都可以被欺骗,但这不可能是偶然发生的。

    附加说明

    可能仍然需要检查是否可以检索 2D 上下文。据报道,一些移动浏览器可以为上述两项检查返回 true,但为 .getContext('2d') 返回 null。这就是为什么 Modernizr 也会检查 .getContext('2d') 的结果。然而,WebIDL 和 HTML ——再次——为我们提供了另一个更好的 faster 选项:

    var canvas2DSupported = !!window.CanvasRenderingContext2D;
    

    请注意,我们可以完全跳过检查画布元素并直接检查 2D 渲染支持。 CanvasRenderingContext2D 接口也是 HTML 规范的一部分。

    必须使用getContext方法检测WebGL支持,因为即使浏览器可能支持WebGLRenderingContextgetContext()也可能返回如果浏览器由于驱动程序问题而无法与 GPU 交互并且没有软件实现,则为 null。在这种情况下,首先检查接口允许您跳过检查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%。

        

    【讨论】:

    • Nokia S60 和 Blackberry Storm 是在您提议的 2D 画布上检测到误报的一些设备之一。不幸的是,移动设备变得非常多毛,供应商不遵守规则。 :( 所以我们最终会进行更完整(即更慢)的测试以确保准确的结果。
    • @Paul:这很有趣,我测试了 BlackBerry Storm 模拟器,对于您的示例和我的示例,它们都返回了 false,似乎它们不提供 CanvasRenderingContext2D 接口。到目前为止,我还无法测试 S60,但我仍然很好奇,可能很快就会这样做。
    • 这很有趣,但只要测试在一百左右毫,那不是很好吗?我想他们都比这快得多。如果你记住一个测试这个的函数,那么你只需要支付一次费用。
    • 我运行了您的基准测试,即使是“慢”方法也可以每秒完成约 800,000 次。同样,如果结果被缓存,那么使用哪种方法的决定应该基于稳健性,而不是性能(假设稳健性存在差异。)
    • @DrewNoakes:是的,你应该总是追求兼容性而不是速度。我的论点是,基于我自己在他评论中提到的至少一个问题浏览器中的测试,我驳斥了 Paul 的兼容性声明。我一直无法测试其他浏览器,但我仍然不相信存在问题。您应该始终致力于在不牺牲兼容性的情况下获得最佳性能。我不是在谈论微优化,但如果您正在运行数百个测试并且它们都未优化,那么是的,它可以有所作为。
    【解决方案3】:

    我通常在创建画布对象时检查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 的一个简单示例,我(个人)更喜欢它而不是优雅降级。

    【讨论】:

    • 第二行的, context是个流浪者吗?
    • @brainjam - 不,我在代码末尾附近使用该变量。我尝试遵循JSLint“建议”(在这种情况下......每个函数只有 1 个var 语句)。
    【解决方案4】:

    为什么不试试modernizr 呢?是一个提供检测能力的JS库。

    引用:

    你有没有想过 CSS 中的 if 语句 提供很酷的功能,例如 边界半径?好吧,有了 Modernizr 你可以做到这一点!

    【讨论】:

    • 我们在modernizr中使用的测试是这样的:return !!document.createElement('canvas').getContext这绝对是最好的测试方式。
    • 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.");
    }
    

    【讨论】:

      【解决方案6】:

      这里可能有一个问题 - 一些客户端不支持 所有 画布方法。

      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)
      

      【讨论】:

        【解决方案7】:

        您可以使用canisuse.js 脚本来检测您的浏览器是否支持画布

        caniuse.canvas()
        

        【讨论】:

          【解决方案8】:

          如果要获取画布的上下文,不妨将其用作测试:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-12-02
            • 1970-01-01
            • 2012-11-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-06-28
            相关资源
            最近更新 更多