Как я могу определить поддержку WebP через Javascript? Я хотел бы использовать обнаружение функций, а не обнаружение браузера, если это возможно, но я не могу найти способ сделать это. Modernizr (www.modernizr.com) его не проверяет.
Обнаружение поддержки WebP
Ответы (17)
Это мое решение - занимает около 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;
- person António Almeida; 26.03.2018
toDataURL('image/webp')
создает PNG.
- person duncanwilcox; 27.07.2020
Я думаю, что что-то вроде этого может сработать:
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");
});
Предпочтительное решение в HTML5
<picture>
<source srcset="/path/to/image.webp" type="image/webp">
<img src="/path/to/image.jpg" alt="insert alt text here">
</picture>
type="image/webp"
критичен для того, чтобы браузер пропустил его, если формат неизвестен!
- person adrianTNT; 14.11.2018
Официальный способ от Google:
Поскольку некоторые старые браузеры имеют частичную поддержку 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.
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<[email protected]>
*/
(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 с 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>
Дополнительные сведения см. здесь
вот простая функция с 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')
}
})
Есть способ проверить поддержку 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)
- person a14m; 11.03.2019
Обнаружение и замена расширений 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');
}
})();
Это гибридный метод HTML / Javascript, который позволит вам определять поддерживаемые типы изображений в порядке предпочтения (ваши предпочтения). В этом примере он вернет первый поддерживаемый тип изображения в браузере и проверит AVIF, WebP, JpegXL и JPG.
<picture style="display:none;">
<source type=image/avif srcset="data:image/avif;base64,AAAAFGZ0eXBhdmlmAAAAAG1pZjEAAACgbWV0YQAAAAAAAAAOcGl0bQAAAAAAAQAAAB5pbG9jAAAAAEQAAAEAAQAAAAEAAAC8AAAAGwAAACNpaW5mAAAAAAABAAAAFWluZmUCAAAAAAEAAGF2MDEAAAAARWlwcnAAAAAoaXBjbwAAABRpc3BlAAAAAAAAAAQAAAAEAAAADGF2MUOBAAAAAAAAFWlwbWEAAAAAAAAAAQABAgECAAAAI21kYXQSAAoIP8R8hAQ0BUAyDWeeUy0JG+QAACANEkA= 1x">
<source type=image/webp srcset="data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA 1x">
<source type=image/jxl srcset="data:image/jxl;base64,/woAEBAJCAQBACwASxLFgoUJEP3D/wA= 1x">
<img onload=console.log(this.currentSrc.substring(this.currentSrc.indexOf(':')+1,this.currentSrc.indexOf(';'))) src="data:image/jpg;base64,/9j/4AAQSkZJRgABAQIAHAAcAAD/2wBDAAMDAwMDAwMDAwMEBAQEBAYFBQUFBgkGBwYHBgkOCAoICAoIDgwPDAsMDwwWEQ8PERYZFRQVGR4bGx4mJCYyMkP/wgALCAABAAEBAREA/8QAFAABAAAAAAAAAAAAAAAAAAAACf/aAAgBAQAAAABU/wD/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/9oACAEBAAE/AH//2Q==">
</picture>
Вы можете заменить функцию журнала на все, что вам нужно.
Преимущества такого подхода:
- вам не нужно создавать и запрашивать кучу объектов в Javascript, поэтому это эффективно
- Браузеру не нужно загружать изображения, они закодированы встроенным образом, поэтому работают быстро и синхронно. Вы можете вставить это куда угодно и получить ответ в следующей строке без обратных вызовов.
- Браузер создаст результат изображения только для первой поддерживаемой строки, поэтому он эффективен.
- Добавить поддержку будущих изображений легко, добавив одну строку.
- Вы можете заказать изображения для любого приоритета, который вы будете использовать в своем приложении.
- Вы можете превратить это в отдельные тесты, обрезав типы изображений, которые вам не нужны.
- Это должно работать, даже если элемент PICTURE не поддерживается, но требует currentSrc, поэтому IE11 не сработает. В этом случае просто проверьте currentSrc в img или предположите, что поддержка JPG всегда присутствует.
РЕДАКТИРОВАТЬ: удален разрыв строки, который попал в пример, спасибо.
Используя ответ @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;
}
now
: modernizr.com/download? webp-setclasses & q = webp - person suther   schedule 30.12.2020