Wie kann ich die Unterstützung für WebP über Javascript erkennen? Wenn möglich, würde ich lieber die Feature-Erkennung als die Browser-Erkennung verwenden, aber ich kann keinen Weg finden, dies zu tun. Modernizr ( www.modernizr.com ) prüft nicht darauf.
javascript
html
image
webp
Snostorm
quelle
quelle
Antworten:
Dies ist meine Lösung - dauert ungefähr 6 ms und ich denke, WebP ist nur eine Funktion für einen modernen Browser. Verwendet einen anderen Ansatz mit der Funktion canvas.toDataUrl () anstelle von image, um die Funktion zu erkennen:
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; } }
quelle
webp = e => document.createElement('canvas').toDataURL('image/webp').indexOf('data:image/webp') == 0;
Ich denke so etwas könnte funktionieren:
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'; })();
In Firefox und IE wird der "Onload" -Handler überhaupt nicht aufgerufen, wenn das Bild nicht verstanden werden kann, und stattdessen wird der "Onerror" aufgerufen.
Sie haben jQuery nicht erwähnt, aber als Beispiel für den Umgang mit der Asynchronität dieser Prüfung können Sie ein jQuery-Objekt "Zurückgestellt" zurückgeben:
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(); }
Dann könnten Sie schreiben:
hasWebP().then(function() { // ... code to take advantage of WebP ... }, function() { // ... code to deal with the lack of WebP ... });
Hier ist ein jsfiddle-Beispiel.
Ein erweiterter Prüfer: http://jsfiddle.net/JMzj2/29/ . Dieser lädt Bilder von einer Daten-URL und prüft, ob sie erfolgreich geladen wurden. Da WebP jetzt auch verlustfreie Bilder unterstützt, können Sie überprüfen, ob der aktuelle Browser nur verlustbehaftetes WebP oder auch verlustfreies WebP unterstützt. (Hinweis: Dies überprüft implizit auch die Unterstützung von Daten-URLs.)
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"); });
quelle
Bevorzugte Lösung in
HTML5
<picture> <source srcset="/path/to/image.webp" type="image/webp"> <img src="/path/to/image.jpg" alt="insert alt text here"> </picture>
Wiki auf W3C
quelle
type="image/webp"
ist wichtig, damit der Browser es bei unbekanntem Format überspringen kann!Offizieller Weg von Google:
Da einige alte Browser Webp teilweise unterstützen , ist es besser, genauer anzugeben, welche Webp-Funktion Sie verwenden und diese bestimmte Funktion erkennen möchten. Hier ist die offizielle Empfehlung von Google, wie eine bestimmte Webp-Funktion erkannt werden kann:
// 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]; }
Anwendungsbeispiel:
check_webp_feature('lossy', function (feature, isSupported) { if (isSupported) { // webp is supported, // you can cache the result here if you want } });
Beachten Sie, dass das Laden von Bildern nicht blockierend und asynchron ist . Dies bedeutet, dass jeder Code, der von der WebP-Unterstützung abhängt, vorzugsweise in die Rückruffunktion eingefügt werden sollte.
Beachten Sie auch, dass andere synchrone Lösungen mit Firefox 65 nicht gut funktionieren
quelle
Dies ist eine alte Frage, aber Modernizr unterstützt jetzt die Webp-Erkennung.
http://modernizr.com/download/
Suchen Sie
img-webp
unter Nicht-Kern-Erkennungen.quelle
Hier ist eine Version von James Westgates Antwort in 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: falsch
FF65: wahr
Chrome: stimmt
Ich mag die synchrone Antwort von Rui Marques, aber leider gibt FF65 trotz der Fähigkeit, WebP anzuzeigen, immer noch false zurück.
quelle
Hier ist Code, ohne ein Bild anfordern zu müssen. Aktualisiert mit der neuen Geige von 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'; });
quelle
WebPJS verwendet eine intelligentere Erkennung der WebP-Unterstützung, ohne dass externe Bilder erforderlich sind: http://webpjs.appspot.com/
quelle
Ich habe festgestellt, dass die Erkennung von Webp-Unterstützungsfunktionen 300 + ms erfordert, wenn die Seite JavaScript-lastig ist. Also habe ich ein Skript mit Caching-Funktionen geschrieben:
Es wird nur einmal erkannt, wenn der Benutzer zum ersten Mal auf die Seite zugreift.
/** * @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(); }); }; })();
quelle
Es gibt eine Möglichkeit, die webP-Unterstützung sofort zu testen . Es ist synchron und genau, sodass Sie nicht auf einen Rückruf warten müssen, um Bilder zu rendern.
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; }
Diese Methode hat meine Renderzeit dramatisch verbessert
quelle
image/webp
aber in diesem Fall false zurückgibt (funktioniert aber sowohl mit Safari als auch mit Chrome korrekt)Hier ist eine einfache Funktion mit Promise, die auf Pointys Antwort basiert
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 }) }
quelle
Meine Kurzversion. Ich habe es verwendet, um Browser webP oder jpg / png zu geben.
Google isst das und das alte iPhone (f̶u̶c̶k̶i̶n̶g̶ ̶s̶h̶e̶e̶t̶ -safari) funktioniert auch großartig!
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') } })
quelle
/* 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. :) -->
quelle
WebP-Bilder mit htaccess
Fügen Sie Folgendes in Ihre
.htaccess
Datei ein, und JPG / PNG-Bilder werden durch WebP-Bilder ersetzt, wenn sie sich im selben Ordner befinden.<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>
Lesen Sie hier mehr
quelle
Webp-Erweiterung JavaScript erkennen und ersetzen:
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'); } })();
quelle
Mit der Antwort von @ Pointy ist dies für
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); } } } }
quelle
Verbesserte Version für Firefox basierend auf Rui Marques. Ich habe den Scan für die verschiedenen Zeichenfolgen basierend auf Kommentaren zu dieser Antwort hinzugefügt.
Wenn diese Verbesserung von der Community akzeptiert wird, sollte sie in dieser Antwort bearbeitet werden.
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; }
quelle