Javascript を介した WebP のサポートを検出するにはどうすればよいですか? 可能であれば、ブラウザー検出ではなく機能検出を使用したいのですが、その方法が見つかりません。Modernizr ( www.modernizr.com ) はそれをチェックしません。
21 に答える
このようなものがうまくいくと思います:
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 ...
});
より高度なチェッカー: 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");
});
画像をリクエストする必要のないコードを次に示します。qwerty の新しいフィドルで更新されました。
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';
});
ページの JavaScript が重い場合、webp サポート機能の検出には 300 ミリ秒以上かかることがわかりました。そこで、キャッシュ機能を備えたスクリプトを作成しました。
- スクリプト キャッシュ
- ローカル ストレージ キャッシュ
ユーザーが最初にページにアクセスしたときに一度だけ検出されます。
/**
* @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();
});
};
})();
WebPJS は、外部画像を必要としない、よりスマートな WebP サポート検出を使用します: http://webpjs.appspot.com/
これは、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
})
}
素晴らしいニュース。Safariで動作します。
document.addEventListener('DOMContentLoaded', function() {
testWebP(document.body)
})
function testWebP(elem) {
const webP = new Image();
webP.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
webP.onload = webP.onerror = function () {
webP.height === 2 ? elem.classList.add('webp-true') : elem.classList.add('webp-false')
}
console.log(webP)
}
ソース: https://gist.github.com/Protoff/d6643387f03d47b44b2d7c3cf7b3e0a0