Обнаружение поддержки WebP - PullRequest
64 голосов
/ 07 апреля 2011

Как я могу определить поддержку WebP через Javascript? Я хотел бы использовать обнаружение функций, а не браузер, если это возможно, но я не могу найти способ сделать это. Modernizr ( www.modernizr.com ) не проверяет это.

Ответы [ 15 ]

73 голосов
/ 01 декабря 2014

Это мое решение - оно занимает около 6 мс, и я считаю, что WebP - это только функция для современного браузера.Использует другой подход, используя функцию canvas.toDataUrl () вместо изображения в качестве способа обнаружения функции:

function canUseWebP() {
    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;
    }

    // very old browser like IE 8, canvas not supported
    return false;
}
51 голосов
/ 07 апреля 2011

Я думаю, что-то вроде этого может работать:

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/. Thisодин загружает изображения из URL-адреса данных и проверяет, успешно ли он загружается.Поскольку теперь WebP также поддерживает изображения без потерь, вы можете проверить, поддерживает ли текущий браузер только Web с потерями или 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");
});
16 голосов
/ 28 октября 2017

Предпочтительное решение в HTML5

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

Wiki на W3C

13 голосов
/ 24 июня 2014

Это старый вопрос, но Modernizr теперь поддерживает обнаружение Webp.

http://modernizr.com/download/

Ищите img-webp в разделе Неосновные обнаружения.

6 голосов
/ 20 ноября 2011

WebPJS использует более умное обнаружение поддержки WebP без внешних изображений: http://webpjs.appspot.com/

5 голосов
/ 07 июня 2012

Вот код без запроса изображения.Обновлено с новой скрипкой 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';
});
3 голосов
/ 10 января 2019

Вот версия ответа Джеймса Вестгейта в 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 = function () {
            res(webP.height === 2);
        };        
    })
};

testWebP().then(hasWebP => console.log(hasWebP));

FF64: false

FF65: true

Chrome: true

Мне нравится синхронный ответ от Руи Маркеса, но, к сожалению, FF65 по-прежнему возвращает false, несмотря на возможность отображения WebP.

3 голосов
/ 09 апреля 2013

Я обнаружил, что функция поддержки 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();
    });
  };

})();
2 голосов
/ 11 февраля 2019

Официальный путь от Google:

Так как некоторые старые браузеры имеют частичную поддержку webp , поэтому лучше уточнить, какую именно функцию webp вы пытаетесь использовать.использовать и обнаруживать эту конкретную функцию, а вот официальная рекомендация 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];
}

// Example Usage
check_webp_feature('lossy', function (feature, isSupported) {
    if (isSupported) {
        // web is supported, 
        // you can cache the result here if you want
    }
});

Обратите внимание, что загрузка изображений неблокируемая и асинхронный .Это означает, что любой код, который зависит от поддержки WebP, предпочтительно должен быть помещен в функцию обратного вызова.

Также обратите внимание , что другие синхронные решения не будут хорошо работать с Firefox 65

2 голосов
/ 05 августа 2018

вот простая функция с 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
  })
}
...