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
Canvas가 없으면 elem.getContext == undefined. !undefined = true, !true = false이므로 정의되지 않은 컨텍스트 나 컨텍스트가 아닌 부울을 반환 할 수 있습니다.
Rich Bradshaw

1
@ 2astalavista 이중 부정 (!!)은 캐스팅과 같습니다. 참 또는 거짓 진술을 부울로 바꿉니다. 예를 들면 다음과 같습니다 var i = 0.. i는 false로 평가되지만 typeof i는 "숫자"를 반환합니다. typeof !! i는 "boolean"을 반환합니다.
사용자 2

부울로 "캐스트"하는 다른 방법은 다음과 같습니다 undefined ? true : false.
vcapra1

1
다른 유형의 캔버스 지원이 있습니다. 초기 브라우저 구현은 지원하지 않았습니다 toDataURL. Opera Mini는 텍스트 API를 지원하지 않는 기본 캔버스 렌더링 만 지원합니다 . 상호 참조를 위해 Opera Mini를 이런 식 으로 제외 할 수 있습니다 .
hexalys

103

브라우저에서 캔버스 지원을 감지하는 데 널리 사용되는 두 가지 방법이 있습니다.

  1. 의 존재 여부를 확인하는 Matt의 제안getContextModernizr 라이브러리와 비슷한 방식으로 사용됩니다.

    var canvasSupported = !!document.createElement("canvas").getContext;
  2. WebIDLHTML 사양에 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;

캔버스 요소 검사를 완전히 건너 뛰고 바로 2D 렌더링 지원 검사를 진행할 수 있습니다. CanvasRenderingContext2D인터페이스는 또한 HTML 사양의 일부입니다.

당신은 해야한다 사용 getContext방법 이 WebGL 검출 브라우저가를 지원하더라도 때문에 지원을 WebGLRenderingContext, getContext()반환 할 수 있습니다 널 (null)을 브라우저 인해 드라이버 문제로 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 캔버스 감지에서 오탐 (false positive)되는 일부 장치 중 하나입니다. 불행히도 모바일은 매우 털이 많으며 공급 업체는 규칙을 따르지 않습니다. :( 그래서 우리는 정확한 결과를 보장하기 위해 더 완전한 (즉, 더 느린) 테스트로 끝납니다.
Paul Irish

@Paul : 흥미 롭습니다. 저는 BlackBerry Storm 에뮬레이터를 테스트 false했습니다. 모두가 예제와 광산 모두에 대해 반환되었으므로 CanvasRenderingContext2D인터페이스를 제공하지 않는 것 같습니다 . 나는 아직 S60을 테스트 할 수 없었지만 여전히 매우 호기심이 많고 곧 그렇게 할 수 있습니다.
Andy E

1
이것은 흥미롭지 만, 테스트가 수백 밀리미터 이하로 들어 오면 괜찮지 않습니까? 어쨌든 그것들보다 훨씬 빠르다고 생각합니다. 이를 테스트하는 기능을 메모하면 비용을 한 번만 지불하면됩니다.
Drew Noakes

1
나는 당신의 벤치 마크를 실행했으며 심지어 '느린'접근조차도 초당 ~ 80 만 번 수행 할 수 있습니다. 다시 결과가 캐시되면 어떤 접근 방식을 사용할 것인지에 대한 결정은 성능이 아닌 견고성에 근거해야합니다 (견고성에 차이가 있다고 가정).
Drew Noakes

@DrewNoakes : 예, 거의 항상 속도에 대한 호환성을 추구해야합니다. 내 주장은 내가 언급 한 문제 브라우저 중 적어도 하나에서 테스트 한 결과를 바탕으로 Paul의 호환성 주장을 반박하고 있다는 것입니다. 다른 브라우저를 테스트 할 수 없지만 문제가 있음을 확신하지 못합니다. 호환성을 유지하면서 항상 최고의 성능을 얻으려고 노력해야합니다. 나는 마이크로 최적화에 대해 이야기하고 있지 않지만, 수백 개의 테스트를 실행하고 있으며 모두 최적화되지 않은 경우에는 차이가 생길 수 있습니다.
Andy 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에 추가 할 수 있습니다. 이것은 개인적으로 Graceful Degradation보다 선호하는 Progressive Enhancement 의 간단한 예입니다 .


, context두 번째 줄에 흩어져 있습니까?
brainjam

7
@brainjam-아니요, 코드 끝 부분에서 해당 변수를 사용합니다. JSLint '권장 사항'(이 경우에는 var함수 당 하나의 명령문 만) 을 따르려고합니다 .
Matt

6

왜하지 않으려 고 모더 나이저를 ? 감지 기능을 제공하는 JS 라이브러리입니다.

인용문:

국경 반경과 같은 멋진 기능을 사용할 수 있도록 CSS에서 if 문을 만들고 싶었던 적이 있습니까? 글쎄, Modernizr을 사용하면 바로 달성 할 수 있습니다!


2
우리가 modernizr에서 사용하는 테스트는 다음과 같습니다. return !!document.createElement('canvas').getContext 확실히 테스트하는 가장 좋은 방법입니다.
Paul Irish

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.