如何检查浏览器是否支持 AVIF 图像

How to check if the browser suppprts AVIF images

如何使用JavaScript检测浏览器是否支持AVIF图像?我查看了 this question,在阅读答案后,我能够构建一个有用的单行函数来检查浏览器对各种图像类型的支持。

const isSupported = (type) => document.createElement('canvas').toDataURL(`image/${type}`).indexOf(`data:image/${type}`) === 0;

它适用于 webp(以及 jpegpng)图像。但它不适用于 avif(和 gif)图像。

所谓不工作,我的意思是即使浏览器支持 AVIF 图像,该函数也会返回 false。

那么,这种方法有什么问题呢?使用JavaScript检测浏览器对avif图像支持的正确方法是什么?

据我所知,浏览器无法使用 canvas 中的 toDataURL 方法创建 AVIF、JXL 或 GIF 文件。我目前使用以下方法通过 Javascript 检测 AVIF 支持:

var avif = new Image();
avif.src = "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A=";
avif.onload = function () {
 /* do something * /
};

另一种方法是使用承诺:

  new Promise(() => {
    const image = new Image();
    image.onerror = () => /* do something */
    image.onload = () => /* do something */
    image.src =
      "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A=";
  }).catch(() => false);

我们用尽可能小的源创建一个新图像并尝试加载它。这在 Firefox、Edge、IE、Chrome、Opera 和 Safari 上可靠地工作并经过测试,包括移动支持。也许您可以根据自己的意图创建一个 oneliner!我希望看到更智能、更精简的方法来检查 AVIF 支持。

来源:

  1. https://avif.io/blog/tutorials/css/#avifsupportdetectionscript
  2. https://github.com/leechy/imgsupport/blob/master/imgsupport.js
  3. https://github.com/justinschmitz97/avif.io/blob/master/components/Layout/Header.tsx

这是另一个真正基于 Promise 的解决方案。

const isFormatSupported = (format, dataUri) =>
  new Promise((resolve, reject) => {
    const image = new Image();

    image.src = `data:image/${format};base64,${dataUri}`;

    image.onload = () => {
      resolve(true);
    };

    image.onerror = () => {
      reject(format.toUpperCase() + "format not supported");
    };
  });

const supportsAvif = await isFormatSupported(
  "avif",
  "AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A="
);