Bagaimana cara mendeteksi dukungan untuk WebP melalui Javascript? Saya ingin menggunakan deteksi fitur daripada deteksi browser jika memungkinkan, tetapi saya tidak dapat menemukan cara untuk melakukannya. Modernizr ( www.modernizr.com ) tidak memeriksanya.
javascript
html
image
webp
snostorm
sumber
sumber
Jawaban:
Ini adalah solusi saya - memakan waktu sekitar 6ms dan saya menganggap WebP hanyalah fitur untuk browser modern. Menggunakan pendekatan berbeda menggunakan fungsi canvas.toDataUrl () sebagai ganti gambar sebagai cara untuk mendeteksi fitur tersebut:
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; } }
sumber
webp = e => document.createElement('canvas').toDataURL('image/webp').indexOf('data:image/webp') == 0;
Saya pikir sesuatu seperti ini mungkin berhasil:
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'; })();
Di Firefox dan IE, penangan "onload" tidak akan dipanggil sama sekali jika gambar tidak dapat dipahami, dan "onerror" yang dipanggil.
Anda tidak menyebutkan jQuery, tetapi sebagai contoh cara menangani sifat asinkron dari pemeriksaan tersebut, Anda dapat mengembalikan objek 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(); }
Kemudian Anda bisa menulis:
hasWebP().then(function() { // ... code to take advantage of WebP ... }, function() { // ... code to deal with the lack of WebP ... });
Berikut adalah contoh jsfiddle.
Pemeriksa yang lebih canggih: http://jsfiddle.net/JMzj2/29/ . Yang ini memuat gambar dari URL data dan memeriksa apakah berhasil memuat. Karena WebP sekarang juga mendukung gambar lossless, Anda dapat memeriksa apakah browser saat ini hanya mendukung WebP lossy atau juga WebP lossless. (Catatan: Ini secara implisit juga memeriksa dukungan URL data.)
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"); });
sumber
Solusi pilihan dalam
HTML5
<picture> <source srcset="/path/to/image.webp" type="image/webp"> <img src="/path/to/image.jpg" alt="insert alt text here"> </picture>
Wiki di W3C
sumber
type="image/webp"
sangat penting agar browser melewatkannya jika formatnya tidak diketahui!Cara resmi oleh Google:
Karena beberapa browser lama memiliki dukungan parsial untuk webp , jadi lebih baik untuk lebih spesifik fitur webp mana yang Anda coba gunakan & deteksi fitur khusus ini, dan berikut adalah rekomendasi resmi Google untuk cara mendeteksi fitur webp tertentu:
// 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]; }
Contoh Penggunaan:
check_webp_feature('lossy', function (feature, isSupported) { if (isSupported) { // webp is supported, // you can cache the result here if you want } });
Perhatikan bahwa pemuatan gambar tidak memblokir dan tidak sinkron . Ini berarti bahwa kode apa pun yang bergantung pada dukungan WebP sebaiknya ditempatkan dalam fungsi callback.
Perhatikan juga bahwa solusi sinkron lainnya tidak akan berfungsi dengan baik dengan Firefox 65
sumber
Ini adalah pertanyaan lama, tetapi Modernizr sekarang mendukung deteksi Webp.
http://modernizr.com/download/
Cari di
img-webp
bawah Deteksi non-inti.sumber
Berikut adalah versi jawaban James Westgate di ES6.
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: salah
FF65: benar
Chrome: benar
Saya suka jawaban sinkron dari Rui Marques, tetapi sayangnya FF65 masih mengembalikan false meskipun memiliki kemampuan untuk menampilkan WebP.
sumber
Berikut adalah kode tanpa harus meminta gambar. Diperbarui dengan biola baru 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'; });
sumber
WebPJS menggunakan deteksi dukungan WebP yang lebih cerdas tanpa memerlukan gambar eksternal: http://webpjs.appspot.com/
sumber
Saya telah menemukan fitur dukungan webp mendeteksi membutuhkan 300 + md saat halaman JavaScript berat. Jadi saya menulis skrip dengan fitur caching:
Ini hanya akan mendeteksi sekali saat pengguna pertama kali mengakses halaman.
/** * @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(); }); }; })();
sumber
Ada cara untuk menguji dukungan webP secara instan . Ini sinkron dan akurat, jadi tidak perlu menunggu panggilan balik untuk merender gambar.
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; }
Metode ini meningkatkan waktu rendering saya secara dramatis
sumber
image/webp
tetapi mengembalikan false dalam kasus ini (tetapi berfungsi di Safari dan Chrome dengan benar)di sini adalah fungsi sederhana dengan Janji berdasarkan respons Pointy
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 }) }
sumber
Versi singkat saya. Saya menggunakannya untuk memberikan webP atau jpg / png browser.
Google makan ini, dan iphone lama (f̶u̶c̶k̶i̶n̶g̶ ̶s̶h̶e̶e̶t̶ -safari) bekerja dengan baik juga!
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') } })
sumber
/* 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. :) -->
sumber
Gambar WebP dengan htaccess
Tempatkan berikut ini di
.htaccess
file Anda dan gambar jpg / png akan diganti dengan gambar WebP jika ditemukan di folder yang sama.<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>
Baca lebih lanjut di sini
sumber
Ekstensi Webp Mendeteksi Dan Penggantian 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'); } })();
sumber
Menggunakan jawaban @ Pointy ini untuk
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); } } } }
sumber
Versi yang ditingkatkan untuk menangani Firefox berdasarkan Rui Marques. Saya menambahkan pemindaian untuk string berbeda berdasarkan komentar ke jawaban itu.
Jika perbaikan ini diterima oleh masyarakat, harus diedit untuk jawaban itu.
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; }
sumber