Javascript aracılığıyla WebP desteğini nasıl tespit edebilirim? Mümkünse tarayıcı algılaması yerine özellik algılamayı kullanmak istiyorum, ancak bunu yapmanın bir yolunu bulamıyorum. Modernizr ( www.modernizr.com ) bunu kontrol etmez.
Javascript aracılığıyla WebP desteğini nasıl tespit edebilirim? Mümkünse tarayıcı algılaması yerine özellik algılamayı kullanmak istiyorum, ancak bunu yapmanın bir yolunu bulamıyorum. Modernizr ( www.modernizr.com ) bunu kontrol etmez.
Yanıtlar:
Bu benim çözümüm - yaklaşık 6ms sürüyor ve WebP'nin yalnızca modern bir tarayıcı için bir özellik olduğunu düşünüyorum. Özelliği algılamanın yolu olarak image yerine canvas.toDataUrl () işlevini kullanarak farklı bir yaklaşım kullanır:
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;
Sanırım böyle bir şey işe yarayabilir:
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 ve IE'de, görüntü anlaşılamıyorsa "yüklenme" işleyicisi hiçbir şekilde çağrılmaz ve bunun yerine "onerror" çağrılır.
JQuery'den bahsetmediniz, ancak bu kontrolün eşzamansız doğasıyla nasıl başa çıkılacağına dair bir örnek olarak bir jQuery "Ertelenmiş" nesnesi döndürebilirsiniz:
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();
}
O zaman yazabilirsin:
hasWebP().then(function() {
// ... code to take advantage of WebP ...
}, function() {
// ... code to deal with the lack of WebP ...
});
Daha gelişmiş bir denetleyici: http://jsfiddle.net/JMzj2/29/ . Bu, görüntüleri bir veri URL'sinden yükler ve başarıyla yüklenip yüklenmediğini kontrol eder. WebP artık kayıpsız görüntüleri de desteklediğinden, mevcut tarayıcının yalnızca kayıplı WebP'yi veya kayıpsız WebP'yi destekleyip desteklemediğini kontrol edebilirsiniz. (Not: Bu, dolaylı olarak veri URL desteğini de kontrol eder.)
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");
});
İçinde tercih edilen çözüm 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"
tarayıcının bilinmeyen format varsa atlaması için kritik öneme sahip!
Google'ın resmi yolu:
Bazı eski tarayıcıların webp için kısmi desteği olduğundan , bu belirli özelliği kullanmaya ve algılamaya çalıştığınız webp özelliğini daha spesifik olmanız daha iyidir ve işte Google'ın belirli bir webp özelliğini nasıl algılayacağınıza dair resmi önerisi :
// 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];
}
Örnek Kullanım:
check_webp_feature('lossy', function (feature, isSupported) {
if (isSupported) {
// webp is supported,
// you can cache the result here if you want
}
});
Görüntü yüklemenin engellemez ve asenkron olduğunu unutmayın . Bu, WebP desteğine bağlı herhangi bir kodun tercihen geri arama işlevine yerleştirilmesi gerektiği anlamına gelir.
Ayrıca diğer zaman uyumlu çözümlerin Firefox 65 ile iyi çalışmayacağını unutmayın .
Bu eski bir sorudur, ancak Modernizr artık Webp algılamayı desteklemektedir.
http://modernizr.com/download/
img-webp
Çekirdek olmayan algılamalar altında arayın .
İşte James Westgate'in ES6'daki cevabının bir versiyonu.
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: yanlış
FF65: doğru
Chrome: doğru
Rui Marques'in eşzamanlı cevabını seviyorum, ancak ne yazık ki FF65, WebP'yi görüntüleme yeteneğine sahip olmasına rağmen hala yanlış döndürüyor.
İşte bir görüntü talep etmek zorunda kalmadan kod. Qwerty'nin yeni kemanıyla güncellendi.
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, harici görüntü gerektirmeden daha akıllı WebP desteği algılaması kullanır: http://webpjs.appspot.com/
Sayfa JavaScript ağır olduğunda webp destek özelliği algılamanın 300 + ms gerektirdiğini buldum. Bu yüzden önbelleğe alma özellikleri olan bir komut dosyası yazdım :
Kullanıcı sayfaya ilk eriştiğinde yalnızca bir kez algılar.
/**
* @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 desteğini anında test etmenin bir yolu var . Senkronize ve doğrudur, bu nedenle görüntüleri oluşturmak için geri aramayı beklemeye gerek yoktur.
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;
}
Bu yöntem, oluşturma süremi önemli ölçüde iyileştirdi
image/webp
bu durumda destekliyor ancak yanlış döndürüyor (ancak hem Safari hem de Chrome'da doğru çalışıyor)
İşte Pointy'nin yanıtına dayalı Promise ile basit bir işlev
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
})
}
Kısa versiyonum. Tarayıcıya webP veya jpg / png vermek için kullandım.
Google bunu yer ve eski iphone (f̶u̶c̶k̶i̶n̶g̶ ̶s̶h̶e̶e̶t̶ -safari) da harika çalışıyor!
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. :) -->
Htaccess ile WebP görüntüleri
Aşağıdakileri .htaccess
dosyanıza yerleştirin ve jpg / png resimleri, aynı klasörde bulunursa WebP resimleri ile değiştirilecektir.
<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>
Daha fazlasını buradan okuyun
Webp uzantısı Algılama ve Değiştirme JavaScript'i:
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'nin cevabını kullanmak için bu 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'u Rui Marques'e dayalı olarak işlemek için geliştirilmiş sürüm. Bu yanıta yapılan yorumlara göre farklı dizeler için taramayı ekledim.
Bu gelişme topluluk tarafından kabul edilirse, bu cevaba göre düzenlenmelidir.
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;
}