Javascript 检测 WebP 支持

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5573096/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 17:52:18  来源:igfitidea点击:

Detecting WebP support

javascripthtmlimagewebp

提问by snostorm

How can I detect support for WebP via Javascript? I'd like to use feature detection rather than browser detection if possible, but I can't find a way to do so. Modernizr (www.modernizr.com) doesn't check for it.

如何通过 Javascript 检测对 WebP 的支持?如果可能,我想使用功能检测而不是浏览器检测,但我找不到这样做的方法。Modernizr ( www.modernizr.com) 不检查它。

回答by Rui Marques

This is my solution - is taking around 6ms and I'm considering WebP is only a feature for a modern browser. Uses a different approach using canvas.toDataUrl() function instead of image as the way to detect the feature:

这是我的解决方案 - 大约需要 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;
}

回答by Pointy

I think something like this might work:

我认为这样的事情可能会奏效:

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

In Firefox and IE, the "onload" handler just won't be called at all if the image can't be understood, and the "onerror" is called instead.

在 Firefox 和 IE 中,如果无法理解图像,则根本不会调用“onload”处理程序,而是调用“onerror”。

You didn't mention jQuery, but as an example of how to deal with the asynchronous nature of that check you could return a jQuery "Deferred" object:

您没有提到 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();
}

Then you could write:

然后你可以写:

hasWebP().then(function() {
  // ... code to take advantage of WebP ...
}, function() {
  // ... code to deal with the lack of WebP ...
});

Here is a jsfiddle example.

这是一个 jsfiddle 示例。



A more advanced checker: http://jsfiddle.net/JMzj2/29/. This one loads images from a data URL and checks whether it loads successfully. Since WebP now also supports lossless images, you could check whether the current browser supports just lossy WebP or also lossless WebP. (Note: This implicitly also checks for data URL support.)

更高级的检查器: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");
});

回答by Andrei Krasutski

Preferred solution in HTML5

首选解决方案 HTML5

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

Wiki on W3C

W3C 上的 Wiki

回答by Jake Wilson

This is an old question, but Modernizr now supports Webp detection.

这是一个老问题,但 Modernizr 现在支持 Webp 检测。

http://modernizr.com/download/

http://modernizr.com/download/

Look for img-webpunder Non-core detects.

img-webp在非核心检测下查找。

回答by AbdelHady

Official way by Google:

谷歌官方方式:

Since some old browsers have partial support for webp, so it is better to be more specific which webp feature you are trying to use & detect this specific feature, and here is Google's official recommendationfor how to detect a specific webp feature:

由于一些旧浏览器对 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];
}

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

Note that image-loading is non-blocking and asynchronous. This means that any code that depends on WebP support should preferably be put in the callback function.

请注意,图像加载是非阻塞和异步的。这意味着任何依赖于 WebP 支持的代码都最好放在回调函数中。

Also notethat other synchronous solutions won't work well with Firefox 65

另请注意,其他同步解决方案不适用于Firefox 65

回答by RoccoB

Here's a version of James Westgate's answer in ES6.

这是 ES6 中 James Westgate 答案的一个版本。

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

FF64:假

FF65: true

FF65:真的

Chrome: true

铬:真的

I love the synchronous answer from Rui Marques, but unfortunately FF65 still returns false despite having the ability to display WebP.

我喜欢 Rui Marques 的同步回答,但不幸的是,尽管能够显示 WebP,FF65 仍然返回 false。

回答by James Westgate

Here is code without having to request an image. Updated with qwerty's new fiddle.

这是无需请求图像的代码。更新了 qwerty 的新小提琴。

http://jsfiddle.net/z6kH9/

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

回答by unxed

WebPJS uses smarter WebP support detection with no external images required: http://webpjs.appspot.com/

WebPJS 使用更智能的 WebP 支持检测,无需外部图像:http://webpjs.appspot.com/

回答by sorrycc

I've found webp support feature detect requires 300+ms when the page is JavaScript heavy. So I wrote a scriptwith caching features:

我发现当页面是 JavaScript 时,webp 支持功能检测需要 300+ms。所以我写了一个带有缓存功能的脚本

  • script cache
  • localstorage cache
  • 脚本缓存
  • 本地存储缓存

It will only detect once when user first accessing the page.

它只会在用户第一次访问页面时检测一次。

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

})();

回答by Guy Sopher

There is a way to test webP support instantly. It's sync and accurate, so there is no need to wait for a callback to render images.

有一种方法可以立即测试 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;
}

This method improved my rendering time dramatically

这种方法大大改善了我的渲染时间