वेबपी सपोर्ट का पता लगाना


99

मैं जावास्क्रिप्ट के माध्यम से वेबपी के लिए समर्थन का पता कैसे लगा सकता हूं? यदि संभव हो तो मैं ब्राउज़र डिटेक्शन के बजाय फ़ीचर डिटेक्शन का उपयोग करना चाहता हूं, लेकिन मुझे ऐसा करने का कोई तरीका नहीं मिल रहा है। Modernizr ( www.modernizr.com ) इसके लिए जाँच नहीं करता है।


1
यदि आप ऐसी छवि को छवि तत्व में लोड करते हैं, और फिर उस ब्राउज़र में चौड़ाई और ऊंचाई की जांच करते हैं जो प्रारूप का समर्थन नहीं करता है , तो क्या आपको कुछ भी मिलता है?
नुकीले

(मेरा मतलब था "इमेज ऑब्जेक्ट ", एलिमेंट नहीं। जैसे, "न्यू इमेज ()" ...)
पॉइंटी

अछा लगता है। मुझे इस तरह से "I do support WebP" मिल सकता है; लेकिन मुझे "मैं वेबपी का समर्थन नहीं करता" नहीं मिल सकता है।
22


2
@Simon_Weaver सवाल और टिप्पणियाँ सभी कई साल पुरानी हैं। पुराने प्रश्नों को किसी भी महत्वपूर्ण तरीके से "बनाए रखा" जाता है; हालांकि आप हमेशा एक नया उत्तर जोड़ने के लिए स्वतंत्र हैं।
पोइंटी

जवाबों:


118

यह मेरा समाधान है - लगभग 6ms ले रहा है और मैं विचार कर रहा हूं कि वेबपी केवल एक आधुनिक ब्राउज़र के लिए एक विशेषता है। सुविधा का पता लगाने के तरीके के रूप में कैनवस के बजाय कैनवस के साथ एक अलग दृष्टिकोण का उपयोग करता है।

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;
 }
}

7
यह स्वीकृत उत्तर होना चाहिए, क्योंकि नेटवर्क संसाधन या डेटा URI की ओर इशारा करने के कारण अन्य सभी में देरी होती है
imal hasaranga perera

6
सरलीकृत संस्करण:webp = e => document.createElement('canvas').toDataURL('image/webp').indexOf('data:image/webp') == 0;
एंटोनियो अल्मेडा

39
यह फ़ायरफ़ॉक्स 65 में काम नहीं करता है जो वेबप को प्रदर्शित करने का समर्थन करता है, लेकिन कैनवास तत्व से वेबपीआर डेटा यूआरएल नहीं बनाता है।
carlcheel

4
इसे प्यार करें क्योंकि यह तुल्यकालिक है, हालांकि @carlel सही है। FF 65 (जिसमें वेबप सपोर्ट है) अभी भी यहां गलत है :-(
राकोबो

13
यह बहुत अच्छा होगा अगर यह FF65 और Edge18 के लिए काम करे। वे दोनों वेबप का समर्थन करते हैं लेकिन कैनवास को "डेटा: इमेज / पीएनजी" के साथ क्रमबद्ध करते हैं
अपरिभाषित

55

मुझे लगता है कि इस तरह से कुछ काम हो सकता है:

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';
})();

फ़ायरफ़ॉक्स और IE में, "ओनलोड" हैंडलर को बिल्कुल नहीं बुलाया जाएगा अगर छवि को समझा नहीं जा सकता है, और इसके बजाय "ऑनरोर" कहा जाता है।

आपने 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 ...
});

यहाँ एक 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");
});

बहुत बढ़िया! यह FF, Chrome और IE 9. में काम करता है। किसी कारण से यह IE8 या IE7 में काम नहीं कर रहा है।
dieki 22

यह IE7 में मेरे लिए काम करता है - मैं अभी जवाब के अंत से जुड़ा हुआ jsFiddle की कोशिश करो।
नुकीले

वैसे मेरे मूल उत्तर में सिर्फ "ऑनलोड" था - मुझे नहीं पता था कि छवि वस्तुओं के लिए एक "ऑनरोर" भी था :-)
Pointy

ओह, दुआ। मैंने एक डेटा का उपयोग किया: एक छवि के बजाय url, और IE7 इसका समर्थन नहीं करता है। : P
dieki

1
मुझे बस एहसास हुआ कि मुझे डेटा के साथ ठीक से काम करने के लिए IE8 मिल सकता है: यूआरएल, और IE7 को इसके लिए एक त्रुटि फेंकने के लिए; समस्या यह थी कि वे सीधे जावास्क्रिप्ट में उनका समर्थन नहीं करते थे। देखें: jsfiddle.net/HaLXz
dieki

37

में पसंदीदा समाधान HTML5

<picture>
  <source srcset="/path/to/image.webp" type="image/webp">
  <img src="/path/to/image.jpg" alt="insert alt text here">
</picture>

W3C पर विकी


2
पूरी तरह से काम करता है, type="image/webp"यह ब्राउज़र के लिए महत्वपूर्ण है अगर इसे अज्ञात प्रारूप को छोड़ दें!
adrianTNT

7
यह अच्छा है, लेकिन यह पृष्ठभूमि छवियों के लिए काम नहीं करता है, और यदि आप किसी साइट पर वेब को रेट्रोफिटिंग कर रहे हैं, और इसके लिए आपके html को संशोधित करने की आवश्यकता होती है, तो इसका मतलब यह भी है कि आपकी सीएसएस में सभी स्थानों को संशोधित करना है जो कि img टैग को संदर्भित करता है।
kloddant

1
हाँ यह समस्या का सबसे अच्छा समाधान है। धन्यवाद
Janith

क्या सभी ब्राउज़र जो वेबप का समर्थन करते हैं, चित्र-तत्व का भी समर्थन करते हैं?
मोलारत

1
यद्यपि देशी एचटीएमएल 5 बेहतर है, अधिकांश ब्राउज़र जेपीजी और डब्ल्यूईबीपी दोनों को लोड करते हैं, जो डाउनलोड समय पर नकारात्मक प्रभाव डालते हैं। गहराई में: smashingmagazine.com/2013/05/…
Jan Werkhoven

25

Google द्वारा आधिकारिक तरीका:

चूँकि कुछ पुराने ब्राउज़रों में वेबप के लिए आंशिक समर्थन है , इसलिए यह अधिक विशिष्ट होना बेहतर है कि आप किस वेबप फ़ीचर का उपयोग कर रहे हैं और इस विशिष्ट फ़ीचर का पता लगाने की कोशिश कर रहे हैं, और यहाँ एक विशिष्ट वेब फ़ीचर का पता लगाने के लिए Google की आधिकारिक अनुशंसा है :

// 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
    }
});

ध्यान दें कि छवि-लोडिंग गैर-अवरुद्ध और अतुल्यकालिक है । इसका मतलब है कि कोई भी कोड जो वेबपी सपोर्ट पर निर्भर करता है उसे अधिमानतः कॉलबैक फ़ंक्शन में रखा जाना चाहिए।

यह भी ध्यान दें कि अन्य तुल्यकालिक समाधान फ़ायरफ़ॉक्स 65 के साथ अच्छी तरह से काम नहीं करेंगे


17

यह एक पुराना प्रश्न है, लेकिन माडर्निज़्र अब वेबप पता लगाने का समर्थन करता है।

http://modernizr.com/download/

img-webpनॉन-कोर डिटेक्ट्स के तहत देखें ।


1
स्रोत यह देखने के लिए उपयोगी है कि उन्होंने क्या किया था github.com/Modernizr/Modernizr/blob/…
Simon_Weaver

मेरे लिए इसने काफी मज़बूती से काम किया है और यह आपको अधिक लचीलेपन के लिए css classes .webp और .no-webp के साथ काम करने की अनुमति देता है।
मोलारत

13

यहाँ 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: सच है

क्रोम: सच है

मुझे रुई मार्केज़ से सिंक्रोनस उत्तर पसंद है, लेकिन दुर्भाग्य से FF65 अभी भी वेबपी को प्रदर्शित करने की क्षमता के बावजूद गलत है।


8

यहाँ एक छवि का अनुरोध किए बिना कोड है। क्यूवर्टी की नई बेला के साथ अपडेट किया गया।

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';
});

5
वह मेरे लिए पूरी तरह से टूट गया था। मैंने इसे forked किया और यह काम किया: jsfiddle.net/z6kH9
qwerty

क्या यह सभी ब्राउज़रों में काम करेगा? मैं Safari + FF65 + में अन्य समाधानों के मुद्दों की बात कर रहा हूँ।
मोलारत

मुझे लगता है कि यह सबसे अच्छा समाधान है। अभी भी पुराने ब्राउज़रों पर परीक्षण देखना चाहते हैं, और वे ब्राउज़र जो वेब का समर्थन नहीं कर रहे हैं।
कोस्टानोस

5

WebPJS किसी भी बाहरी छवियों के साथ आवश्यक WebP समर्थन पहचान का उपयोग करता है: http://webpjs.appspot.com/


स्क्रिप्ट जो वे अपनी फ़ाइल को लोड करने के लिए उपयोग करते हैं, वास्तव में उनकी फ़ाइल का उपयोग किए बिना उपयोग किया जा सकता है। यदि आप कोई वेबपी सपोर्ट नहीं चाहते हैं तो बस अंदर की जगह ले लें।
tgrosinger

1
ऐसा लगता है कि वे डेटा यूआरएल का उपयोग कर रहे हैं, के साथ क्या मैं का उपयोग कर समाप्त हो गया है।
डेकी

5

मैंने पाया है कि वेबप सपोर्ट फीचर का पता लगाने के लिए 300 + ms की आवश्यकता होती है जब पेज जावास्क्रिप्ट भारी होता है। इसलिए मैंने कैशिंग विशेषताओं के साथ एक स्क्रिप्ट लिखी :

  • स्क्रिप्ट कैश
  • स्थानीय भंडार कैश

यह केवल तब पता चलेगा जब उपयोगकर्ता पहली बार पृष्ठ तक पहुंचेगा।

/**
 * @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();
    });
  };

})();

3

/* 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. :) -->


2

वेबपी समर्थन का तुरंत परीक्षण करने का एक तरीका है । यह सिंक और सटीक है, इसलिए छवियों को प्रस्तुत करने के लिए कॉलबैक की प्रतीक्षा करने की आवश्यकता नहीं है।

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;
}

इस पद्धति ने मेरे प्रतिपादन के समय में नाटकीय रूप से सुधार किया


5
फ़ायरफ़ॉक्स पर काम नहीं करता ... जो समर्थन करता है image/webpलेकिन इस मामले में गलत है (लेकिन सफारी और क्रोम दोनों पर सही तरीके से काम करता है)
a14m

2

यहाँ पॉइंटी की प्रतिक्रिया के आधार पर वादा के साथ एक सरल कार्य है

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
  })
}

हालांकि यह कोड प्रश्न का उत्तर दे सकता है, लेकिन समस्या को हल करने के तरीके के बारे में अतिरिक्त संदर्भ प्रदान करता है और यह समस्या को हल करता है ताकि उत्तर के दीर्घकालिक मूल्य में सुधार हो सके।
निक 3500

मैंने सोचा कि यह बहुत स्पष्ट है, हम बेस 64 स्ट्रिंग (जो 1px चौड़ा और उच्च है) से एक वेब छवि को लोड करने की कोशिश करते हैं, अगर हमने इसे ठीक से लोड किया है (ऑनलोड कहा जाता है) यह समर्थित है, यदि नहीं (ऑनरोर नाम से) यह नहीं है, तो मैं बस इसे लपेटता हूं एक वादा में।
लियोन नवोन

2

मेरा लघु संस्करण। मैंने इसका उपयोग ब्राउज़र वेबपी या jpg / png देने के लिए किया है।

Google इसे खाएं, और पुराने iPhone (f̶u thisc̶k̶i̶n̶g̶ ̶s̶h̶e̶est̶ -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')
      }
      
})


1

Htaccess के साथ वेबपी छवियां

अपनी .htaccessफ़ाइल में निम्न रखें और यदि एक ही फ़ोल्डर में jpg / png चित्र वेबप छवियों से बदल दिए जाएँगे।

<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>

यहाँ और पढ़ें


1

वेब एक्सटेंशन विस्तार और प्रतिस्थापन जावास्क्रिप्ट:

 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');
  }
})();

1

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;
}

0

@ पॉइंट्टी के उत्तर का उपयोग करना इस प्रकार है 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);
            }
        }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.