不支持检测HTML5 <canvas>的最佳方法

bra*_*jam 137 javascript html5 canvas progressive-enhancement graceful-degradation

处理浏览器不支持HTML5 <canvas>标记的情况的标准方法是嵌入一些后备内容,如:

<canvas>Your browser doesn't support "canvas".</canvas>
Run Code Online (Sandbox Code Playgroud)

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

Pau*_*ish 215

这是Modernizr中使用的技术,基本上每个其他库都可以进行画布工作:

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

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

if (!isCanvasSupported()){ ...
Run Code Online (Sandbox Code Playgroud)

  • 如果没有Canvas,`elem.getContext == undefined`.`!undefined = true`,和`!true = false`,所以这让我们返回一个bool,而不是undefined或上下文. (16认同)
  • 为什么双重否定(!!)代表什么? (14认同)

And*_*y E 103

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

  1. Matt建议检查是否存在getContext,也用于Modernizr库的类似方式:

    var canvasSupported = !!document.createElement("canvas").getContext;
    
    Run Code Online (Sandbox Code Playgroud)
  2. 检查HTMLCanvasElement接口是否存在,如WebIDLHTML规范所定义.在IE 9团队的博客文章中也推荐了这种方法.

    var canvasSupported = !!window.HTMLCanvasElement;
    
    Run Code Online (Sandbox Code Playgroud)

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

  • 每个已知的支持画布的浏览器 - 包括IE 9 - 都实现了这个界面;
  • 它更简洁明了,代码正在做什么;
  • 所有浏览器getContext方法都明显变慢,因为它涉及创建HTML元素.当你需要尽可能多地挤压性能时(例如在Modernizr这样的库中),这并不理想.

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

补充说明

可能仍然需要检查是否可以检索2D上下文.据了解,一些移动浏览器可以同时为上述检查返回true,但返回null.getContext('2d').这就是Modernizr也检查结果的原因.getContext('2d').但是,WebIDL和HTML - 再次 - 为我们提供了另一个更好,更快的选择:

var canvas2DSupported = !!window.CanvasRenderingContext2D;
Run Code Online (Sandbox Code Playgroud)

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

必须使用该getContext方法来检测WebGL支持,因为即使浏览器可能支持该方法WebGLRenderingContext,如果浏览器由于驱动程序问题而无法与GPU接口且没有软件实现,则getContext()可能返回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
    }
}
Run Code Online (Sandbox Code Playgroud)

绩效比较

getContext在Firefox 11和Opera 11中,该方法的性能降低了85-90%,在Chromium 18中降低了55%.

    简单比较表,单击以在浏览器中运行测试

  • 诺基亚S60和黑莓风暴是其中一些设备,它们会对您提出的2D画布检测到误报.不幸的是,手机变得非常毛茸茸,供应商也不遵守规则.:(所以我们最终得到更完整(即更慢)的测试,以确保准确的结果. (10认同)

Mat*_*att 13

我通常getContext在创建canvas对象时运行检查.

(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);
}());
Run Code Online (Sandbox Code Playgroud)

如果支持,则可以继续画布设置并将其添加到DOM.这是渐进增强的一个简单例子,我个人更喜欢优雅降级.

  • @brainjam - 不,我在代码末尾附近使用该变量.我尝试遵循[JSLint](http://jslint.com)的"建议"(在这种情况下......每个函数只有1个`var`语句). (7认同)

Fro*_*kys 6

为什么不尝试现代化?它是一个提供检测功能的JS库.

引用:

您是否曾想在CSS中使用if语句来获得border-radius等很酷的功能?那么,有了Modernizr你就可以做到这一点!

  • Modernizr是一个有用的库,但是为了检测画布支持而拉入整个库会有点浪费.如果您还需要检测其他功能,我建议您使用它. (4认同)
  • 我们在modernizr中使用的测试是:`return !! document.createElement('canvas').getContext`这绝对是最好的测试方法. (2认同)

小智 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.");
}
Run Code Online (Sandbox Code Playgroud)