Как я могу определить поддержку WebP через Javascript? Я хотел бы использовать обнаружение функций, а не обнаружение браузера, если это возможно, но я не могу найти способ сделать это. Modernizr ( www.modernizr.com ) не проверяет это.
javascript
html
image
webp
snostorm
источник
источник
Ответы:
Это мое решение - занимает около 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; } }
источник
webp = e => document.createElement('canvas').toDataURL('image/webp').indexOf('data:image/webp') == 0;
Я думаю, что что-то вроде этого может сработать:
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"); });
источник
Предпочтительное решение в
HTML5
<picture> <source srcset="/path/to/image.webp" type="image/webp"> <img src="/path/to/image.jpg" alt="insert alt text here"> </picture>
Вики на W3C
источник
type="image/webp"
критично, чтобы браузер пропустил его, если формат неизвестен!Официальный способ от Google:
Поскольку некоторые старые браузеры частично поддерживают webp , поэтому лучше уточнить, какую функцию webp вы пытаетесь использовать и обнаружить эту конкретную функцию, и вот официальная рекомендация Google по обнаружению конкретной функции webp:
// 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, предпочтительно помещать в функцию обратного вызова.
Также обратите внимание, что другие синхронные решения не будут работать с Firefox 65.
источник
Это старый вопрос, но Modernizr теперь поддерживает обнаружение Webp.
http://modernizr.com/download/
Ищите в
img-webp
разделе «Неосновные обнаружения».источник
Вот версия ответа Джеймса Вестгейта в 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: ложь
FF65: правда
Chrome: правда
Мне нравится синхронный ответ от Руи Маркеса, но, к сожалению, FF65 по-прежнему возвращает false, несмотря на возможность отображать WebP.
источник
Вот код без необходимости запрашивать изображение. Обновлено с помощью новой скрипки 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'; });
источник
WebPJS использует более умное определение поддержки WebP без необходимости внешних изображений: http://webpjs.appspot.com/
источник
Я обнаружил, что обнаружение функции поддержки webp требует 300 + мс, когда страница загружена JavaScript. Поэтому я написал скрипт с функциями кеширования:
Он обнаруживает только один раз, когда пользователь впервые обращается к странице.
/** * @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(); }); }; })();
источник
Есть способ мгновенно проверить поддержку 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; }
Этот метод значительно улучшил время рендеринга
источник
image/webp
но в этом случае возвращает false (но правильно работает как в Safari, так и в Chrome)вот простая функция с Promise, основанная на ответе 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 }) }
источник
Моя короткая версия. Я использовал его, чтобы дать браузеру webP или jpg / png.
Google съел это, и старый 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') } })
источник
/* 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. :) -->
источник
Изображения WebP с htaccess
Поместите следующее в свой
.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>
Подробнее здесь
источник
Расширение 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'); } })();
источник
Используя ответ @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); } } } }
источник
Улучшенная версия для работы с Firefox на основе Rui Marques. Я добавил сканирование различных строк на основе комментариев к этому ответу.
Если это улучшение принято сообществом, его следует отредактировать в этом ответе.
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; }
источник