WebPサポートの検出


99

Javascriptを介してWebPのサポートを検出するにはどうすればよいですか?可能であればブラウザ検出ではなく機能検出を使用したいのですが、その方法が見つかりません。Modernizr(www.modernizr.com)はそれをチェックしません。


1
そのような画像をImage要素にロードし、その形式をサポートしていないブラウザで幅と高さを確認すると、何かが得られますか?
とがった2011

(私は要素ではなく「画像オブジェクト」を意味しました。「
newImage

いいね。この方法で「WebPをサポートしています」を取得できます。しかし、「WebPをサポートしていません」を取得できません。
dieki 2011


2
@Simon_Weaver質問とコメントはすべて数年前のものです。古い質問が重要な方法で「維持」されることはめったにありません。ただし、いつでも自由に新しい回答を追加できます。
とがった2018年

回答:


118

これが私の解決策です-約6ミリ秒かかり、WebPは最新のブラウザーの機能にすぎないと考えています。特徴を検出する方法として、画像の代わりにcanvas.toDataUrl()関数を使用する別のアプローチを使用します。

function support_format_webp()
{
 var elem = document.createElement('canvas');

 if (!!(elem.getContext && elem.getContext('2d')))
 {
  // was able or not to get WebP representation
  return elem.toDataURL('image/webp').indexOf('data:image/webp') == 0;
 }
 else
 {
  // very old browser like IE 8, canvas not supported
  return false;
 }
}

7
ネットワークリソースまたはデータURIを指しているために他のすべての遅延があるため、これは受け入れられた答えであるはずです
imal hasaranga perera 2017年

6
簡素化されたバージョン:webp = e => document.createElement('canvas').toDataURL('image/webp').indexOf('data:image/webp') == 0;
Antónioのアルメイダ

39
これは、webpの表示をサポートするFirefox 65では機能しませんが、canvas要素からwebpデータURLを作成することはできません。
carlcheel 2018

4
同期しているのでこれが大好きですが、@ carlcheelは正しいです。FF 65は、(WEBPサポートを持っていること)まだここにはfalseを返します:-(
RoccoB

13
これ、FF65とEdge18で機能する場合に最適です。これらは両方ともサポートWEBPが、「データ:画像/ PNG」とキャンバスをシリアル化
undefinederror

55

私はこのようなものがうまくいくかもしれないと思います:

var hasWebP = false;
(function() {
  var img = new Image();
  img.onload = function() {
    hasWebP = !!(img.height > 0 && img.width > 0);
  };
  img.onerror = function() {
    hasWebP = false;
  };
  img.src = 'http://www.gstatic.com/webp/gallery/1.webp';
})();

FirefoxとIEでは、画像が理解できない場合、「onload」ハンドラーはまったく呼び出されず、代わりに「onerror」が呼び出されます。

jQueryについては触れませんでしたが、そのチェックの非同期性を処理する方法の例として、jQueryの「Deferred」オブジェクトを返すことができます。

function hasWebP() {
  var rv = $.Deferred();
  var img = new Image();
  img.onload = function() { rv.resolve(); };
  img.onerror = function() { rv.reject(); };
  img.src = 'http://www.gstatic.com/webp/gallery/1.webp';
  return rv.promise();
}

次に、次のように書くことができます。

hasWebP().then(function() {
  // ... code to take advantage of WebP ...
}, function() {
  // ... code to deal with the lack of WebP ...
});

これがjsfiddleの例です。


より高度なチェッカー:http//jsfiddle.net/JMzj2/29/。これはデータURLから画像をロードし、正常にロードされるかどうかをチェックします。WebPはロスレス画像もサポートするようになったため、現在のブラウザがロスレスWebPのみをサポートしているか、ロスレスWebPもサポートしているかを確認できます。(注:これは暗黙的にデータURLサポートもチェックします。)

var hasWebP = (function() {
    // some small (2x1 px) test images for each feature
    var images = {
        basic: "data:image/webp;base64,UklGRjIAAABXRUJQVlA4ICYAAACyAgCdASoCAAEALmk0mk0iIiIiIgBoSygABc6zbAAA/v56QAAAAA==",
        lossless: "data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAQAAAAfQ//73v/+BiOh/AAA="
    };

    return function(feature) {
        var deferred = $.Deferred();

        $("<img>").on("load", function() {
            // the images should have these dimensions
            if(this.width === 2 && this.height === 1) {
                deferred.resolve();
            } else {
                deferred.reject();
            }
        }).on("error", function() {
            deferred.reject();
        }).attr("src", images[feature || "basic"]);

        return deferred.promise();
    }
})();

var add = function(msg) {
    $("<p>").text(msg).appendTo("#x");
};

hasWebP().then(function() {
    add("Basic WebP available");
}, function() {
    add("Basic WebP *not* available");
});

hasWebP("lossless").then(function() {
    add("Lossless WebP available");
}, function() {
    add("Lossless WebP *not* available");
});

驚くばかり!これはFF、Chrome、およびIE9で機能します。何らかの理由でIE8またはIE7では機能しません。
dieki 2011

それはIE7で私のために働きます-私がちょうど答えの終わりにリンクしたjsFiddleを試してください。
とがった2011

さて、私の元の答えはちょうど「オンロード」でした
とがった2011

ああ、そうだね。画像の代わりにデータURLを使用しましたが、IE7はそれをサポートしていません。:P
dieki 2011

1
IE8でdata:urlsを正しく動作させ、IE7でエラーをスローできることに気づきました。問題は、JavaScriptで直接サポートされていないことでした。参照:jsfiddle.net/HaLXz
dieki

37

の推奨ソリューション HTML5

<picture>
  <source srcset="/path/to/image.webp" type="image/webp">
  <img src="/path/to/image.jpg" alt="insert alt text here">
</picture>

W3CのWiki


2
完全にtype="image/webp"機能します。形式が不明な場合にブラウザがスキップするためには、これが重要です。
adrianTNT 2018年

6
これは良いことですが、背景画像では機能しません。また、webpをサイトに後付けする場合は、htmlを変更する必要があります。つまり、css内でimgタグを参照するすべての場所を変更する必要があります。
kloddant

1
はい、これが問題の最善の解決策です。おかげで
Janith

webpをサポートするすべてのブラウザはpicture-elementもサポートしていますか?
モレラット

ネイティブHTML5が望ましいですが、ほとんどのブラウザはJPGとWEBPの両方をロードするため、ダウンロード時間に悪影響を及ぼします。深さ:smashingmagazine.com/2013/05/...
月Werkhoven

24

Googleによる公式の方法:

一部の古いブラウザはwebp部分的にサポートしているため、使用しようとしているwebp機能をより具体的にして、この特定の機能を検出することお勧めします。特定のwebp機能を検出する方法に関するGoogleの公式推奨事項は次のとおりです。

// check_webp_feature:
//   'feature' can be one of 'lossy', 'lossless', 'alpha' or 'animation'.
//   'callback(feature, isSupported)' will be passed back the detection result (in an asynchronous way!)
function check_webp_feature(feature, callback) {
    var kTestImages = {
        lossy: "UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA",
        lossless: "UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==",
        alpha: "UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",
        animation: "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"
    };
    var img = new Image();
    img.onload = function () {
        var result = (img.width > 0) && (img.height > 0);
        callback(feature, result);
    };
    img.onerror = function () {
        callback(feature, false);
    };
    img.src = "data:image/webp;base64," + kTestImages[feature];
}

使用例:

check_webp_feature('lossy', function (feature, isSupported) {
    if (isSupported) {
        // webp is supported, 
        // you can cache the result here if you want
    }
});

画像の読み込みは非ブロッキングで非同期であることに注意してください。つまり、WebPサポートに依存するコードは、コールバック関数に配置することが望ましいということです。

また、他の同期ソリューションはFirefox65ではうまく機能しないことに注意しください


17

これは古い質問ですが、ModernizrはWebp検出をサポートするようになりました。

http://modernizr.com/download/

img-webp非コア検出の下を探します。


1
ソースは、彼らが何をしたか確認するために便利ですgithub.com/Modernizr/Modernizr/blob/...
Simon_Weaver

私にとっては非常に確実に機能し、cssクラスの.webpおよび.no-webpを使用して柔軟性を高めることができます。
モレラット

12

これは、ES6でのJamesWestgateの回答のバージョンです。

function testWebP() {
    return new Promise(res => {
        const webP = new Image();
        webP.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
        webP.onload = webP.onerror = () => {
            res(webP.height === 2);
        };        
    })
};

testWebP().then(hasWebP => console.log(hasWebP));

FF64:false

FF65:本当

Chrome:true

Rui Marquesからの同期応答が大好きですが、残念ながら、WebPを表示する機能があるにもかかわらず、FF65はfalseを返します。


8

これは、画像をリクエストする必要のないコードです。qwertyの新しいフィドルで更新されました。

http://jsfiddle.net/z6kH9/

function testWebP(callback) {
    var webP = new Image();
    webP.onload = webP.onerror = function () {
        callback(webP.height == 2);
    };
    webP.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
};

testWebP(function(support) {
    document.body.innerHTML = support ? 'Yeah man!' : 'Nope';
});

5
それは私にとって完全に壊れていました。私はそれをフォークし、それが仕事作っ:jsfiddle.net/z6kH9
QWERTY

これはすべてのブラウザで機能しますか?Safari + FF65 +の他のソリューションの問題について言及しています。
モレラット

これが最善の解決策だと思います。それでも、古いブラウザやwebpをサポートしていないブラウザでのテストを見たいと思っています。
コスタノス

5

WebPJSは、外部画像を必要とせずに、よりスマートなWebPサポート検出を使用しますhttp//webpjs.appspot.com/


ファイルのロードに使用するスクリプトは、実際にファイルを使用しなくても使用できます。WebPがサポートされていない場合は、内部をやりたいことと置き換えるだけです。
tgrosinger 2011年

1
彼らはデータURLを使用しているようですが、私が最終的に使用したのはそれです。
dieki 2012年

4

ページがJavaScriptで重い場合、webpサポート機能の検出には300ミリ秒以上かかることがわかりました。そこで、キャッシュ機能を備えたスクリプト作成しました。

  • スクリプトキャッシュ
  • ローカルストレージキャッシュ

ユーザーが最初にページにアクセスしたときに1回だけ検出されます。

/**
 * @fileOverview WebP Support Detect.
 * @author ChenCheng<sorrycc@gmail.com>
 */
(function() {

  if (this.WebP) return;
  this.WebP = {};

  WebP._cb = function(isSupport, _cb) {
    this.isSupport = function(cb) {
      cb(isSupport);
    };
    _cb(isSupport);
    if (window.chrome || window.opera && window.localStorage) {
      window.localStorage.setItem("webpsupport", isSupport);
    }
  };

  WebP.isSupport = function(cb) {
    if (!cb) return;
    if (!window.chrome && !window.opera) return WebP._cb(false, cb);
    if (window.localStorage && window.localStorage.getItem("webpsupport") !== null) {
      var val = window.localStorage.getItem("webpsupport");
      WebP._cb(val === "true", cb);
      return;
    }
    var img = new Image();
    img.src = "data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA";
    img.onload = img.onerror = function() {
      WebP._cb(img.width === 2 && img.height === 2, cb);
    };
  };

  WebP.run = function(cb) {
    this.isSupport(function(isSupport) {
      if (isSupport) cb();
    });
  };

})();

3

webPサポートを即座にテストする方法があります。同期していて正確なので、画像をレンダリングするためのコールバックを待つ必要はありません。

function testWebP = () => {
    const canvas = typeof document === 'object' ? 
    document.createElement('canvas') : {};
    canvas.width = canvas.height = 1;
    return canvas.toDataURL ? canvas.toDataURL('image/webp').indexOf('image/webp') === 5 : false;
}

この方法により、レンダリング時間が劇的に改善されました


5
Firefoxの上の仕事は...サポートしませんimage/webpが、falseを返します。この場合、(ただし、正しくサファリとChromeの両方で動作)
a14m

2

これは、Pointyの応答に基づくPromiseを使用した単純な関数です。

let webpSupport = undefined // so we won't have to create the image multiple times
const webp1Px = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA'

function isWebpSupported () {
  if (webpSupport !== undefined) {
    return Promise.resolve(webpSupport)
  }

  return new Promise((resolve, _reject) => {
    const img = new Image()
    img.onload = () => {
      webpSupport = !!(img.height > 0 && img.width > 0);
      resolve(webpSupport)
    }
    img.onerror = () => {
      webpSupport = false
      resolve(webpSupport)
    }
    img.src = webp1Px
  })
}

このコードは質問に答えることができますが、問題を解決する方法や理由に関する追加のコンテキストを提供すると、回答の長期的な価値が向上します。
nic3500 2018

私はそれがかなり明確だと思いました、私たちはbase64文字列(1pxの幅と高さ)からwebp画像をロードしようとします、それを適切にロードした場合(onloadと呼ばれます)それはサポートされます、そうでない場合(onerrorと呼ばれます)そうではありません、私は単にそれをラップしました約束で。
Liron Navon

2

私の短いバージョン。私はブラウザwebPまたはjpg / pngを与えるためにそれを使用しています。

グーグルはこれを食べます、そして古いiphone(f—u—c—k—i—n—g——s—h—e—e—t— -safari)も素晴らしい働きをします!

function checkWebP(callback) {
    var webP = new Image();
    webP.onload = webP.onerror = function () {
        callback(webP.height == 2);
    };
    webP.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
};

checkWebP(function(support) {
      if(support) {
          //Do what you whant =)
         console.log('work webp');
      }else{
          //Do what you whant =)
         console.log('not work, use jgp/png')
      }
      
})


2

/* Here's a one-liner hack that works (without the use/need of any 
   externals...save bytes)...

Your CSS... */

body.no-webp .logo {
  background-image: url('logo.png');
}

body.webp .logo {
  background-image: url('logo.webp');
}
...
<body>
  <!--
  The following img tag is the *webp* support checker. I'd advise you use any 
  (small-sized) image that would be utilized on the current page eventually 
  (probably an image common to all your pages, maybe a logo) so that when 
  it'll be (really) used on the page, it'll be loaded from cache by the 
  browser instead of making another call to the server (for some other image 
  that won't be).

  Sidebar: Using 'display: none' so it's not detected by screen readers and 
  so it's also not displayed (obviously). :)
  -->
  <img 
    style='display: none'
    src='/path/to/low-sized-image.webp'
    onload="this.parentNode.classList.add('webp')"
    onerror="this.parentNode.classList.add('no-webp')"
  />
  ...
</body>


   <!-- PS. It's my first answer on SO. Thank you. :) -->


1

htaccessを使用したWebP画像

以下を.htaccessファイルに配置すると、同じフォルダーにjpg / png画像が見つかった場合はWebP画像に置き換えられます。

<IfModule mod_rewrite.c>
  RewriteEngine On

  # Check if browser support WebP images
  RewriteCond %{HTTP_ACCEPT} image/webp

  # Check if WebP replacement image exists
  RewriteCond %{DOCUMENT_ROOT}/$1.webp -f

  # Serve WebP image instead
  RewriteRule (.+)\.(jpe?g|png)$ $1.webp [T=image/webp,E=accept:1]
</IfModule>

<IfModule mod_headers.c>
  Header append Vary Accept env=REDIRECT_accept
</IfModule>

<IfModule mod_mime.c>
  AddType image/webp .webp
</IfModule>

詳細はこちら


1

Webp拡張機能の検出と置換JavaScript:

 async function supportsWebp() {
  if (!self.createImageBitmap) return false;

  const webpData = 'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=';
  const blob = await fetch(webpData).then(r => r.blob());
  return createImageBitmap(blob).then(() => true, () => false);
}

(async () => {
  if(await supportsWebp()) {
    console.log('webp does support');
  }
  else {
    $('#banners .item').each(function(){
        var src=$(this).find('img').attr('src');
        src = src.replace(".webp", ".jpg");
        $(this).find('img').attr('src',src);
    });
    console.log('webp does not support');
  }
})();

1

RuiMarquesに基づくFirefoxを処理するための改善されたバージョン。その回答へのコメントに基づいて、さまざまな文字列のスキャンを追加しました。

この改善がコミュニティに受け入れられた場合は、その回答に合わせて編集する必要があります。

function canUseWebP()
{
    var elem = document.createElement('canvas');

    if (!!(elem.getContext && elem.getContext('2d')))
    {
        var testString = (!(window.mozInnerScreenX == null)) ? 'png' : 'webp';
        // was able or not to get WebP representation
        return elem.toDataURL('image/webp').indexOf('data:image/' + testString) == 0;
    }

    // very old browser like IE 8, canvas not supported
    return false;
}

0

@Pointyの答えを使用すると、これは次の目的で使用されAngular 2+ます。

import { Injectable } from '@angular/core';
import { Subject }    from 'rxjs/Subject';

@Injectable()
export class ImageService {
    private isWebpEnabledSource = new Subject<boolean>();

    isWebpEnabledAnnounced$ = this.isWebpEnabledSource.asObservable();

    isWebpEnabled() {
        let webpImage = new Image();

        webpImage.src = 'data:image/webp;base64,UklGRjIAAABXRUJQVlA4ICYAAACyAgCdASoCAAEALmk0mk0iIiIiIgBoSygABc6zbAAA/v56QAAAAA==';

        webpImage.onload = () => {
            if (webpImage.width === 2 && webpImage.height === 1) {
                this.isWebpEnabledSource.next(true);
            } else {
                this.isWebpEnabledSource.next(false);
            }
        }
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.