Як я можу виявити підтримку WebP через Javascript? Я хотів би скористатися виявленням функцій, а не виявленням браузера, якщо це можливо, але я не можу знайти спосіб це зробити. Modernizr ( www.modernizr.com ) не перевіряє його.
Як я можу виявити підтримку WebP через Javascript? Я хотів би скористатися виявленням функцій, а не виявленням браузера, якщо це можливо, але я не можу знайти спосіб це зробити. Modernizr ( www.modernizr.com ) не перевіряє його.
Відповіді:
Це моє рішення - займає близько 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 "Відкладений":
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"
це критично важливо для того, щоб браузер пропустив його, якщо невідомий формат!
Офіційний спосіб від 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: правда
Мені подобається синхронна відповідь від Rui Marques, але, на жаль, 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<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;
}