乐趣区

判断浏览器是否支持-webp-的几种解决方法

我们都知道,WebP 是 Google 推出的 WebP 图片格式,它是一种支持有损压缩和无损压缩的图片文件格式,根据 Google 测试,相同的图片,WebP 格式的图片均能比 PNG,JPG 格式的图片节约不少体积,但是其兼容性不是很好,如下:

因此我们需要做一些兼容处理,那么如何判断浏览器支持 webp 呢?下面有几种方法可供参考。

方法一

使用 canvas 的 toDataURL 进行判断

toDataURL 方法在 MDN 解释如下:

HTMLCanvasElement.toDataURL() 方法返回一个包含图片展示的 data URI。可以使用 type 参数其类型,默认为 PNG 格式。图片的分辨率为 96dpi。

  • 如果画布的高度或宽度是 0,那么会返回字符串“data:,”。
  • 如果传入的类型非“image/png”,但是返回的值以“data:image/png”开头,那么该传入的类型是不支持的。
  • Chrome 支持“image/webp”类型。

toDataURL 方法将图片转化为包含 dataURI 的 DOMString,通过 base64 编码前面的图片类型值是 image/webp 进行判断。

比如在谷歌浏览器使用 toDataURL 方法转成 image/webp:

在 Safari 浏览器使用 toDataURL 方法转成 image/webp:

可以发现在不支持 webp 的浏览器进行 toDataURL,得到的图片类型并不是 webp,因此我们可以通过这个进行判断。

实现方法:

var isSupportWebp = function () {
  try {return document.createElement('canvas').toDataURL('image/webp', 0.5).indexOf('data:image/webp') === 0;
  } catch(err) {return false;}
}

isSupportWebp()

方法二

在服务端根据请求 header 信息判断浏览器是否支持 webp

谷歌浏览器上请求图片 header 是这样的:

IE 浏览器请求图片 header 是这样的:

在图片请求发出的时候,Request Headers 里有 Accept,服务端可以根据 Accept 里面是否有 image/webp 进行判断。

方法三

通过加载一张 webp 图片进行判断

const supportsWebp = ({createImageBitmap, Image}) => {if (!createImageBitmap || !Image) return Promise.resolve(false);

  return new Promise(resolve => {const image = new Image();
      image.onload = () => {createImageBitmap(image)
              .then(() => {resolve(true);
              })
              .catch(() => {resolve(false);
              });
      };
      image.onerror = () => {resolve(false);
      };
      image.src = 'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=';
  });
};

const webpIsSupported = () => {
  let memo = null;
  return () => {if (!memo) {memo = supportsWebp(window);
      }
      return memo;
  };
};

webpIsSupported()().then(res => {console.log("是否支持 webp", res)
}).catch(err => {console.log(err)
})

此方法会加载一张 1×1 的白色的正方形背景图,用来测试浏览器是否支持 webp。

在 Google 测试代码:

在 Firefox 测试代码:

在 Safari 测试代码:

Google 官方文档是这样处理的(先加载一个 WebP 图片,如果能获取到图片的宽度和高度,就说明是支持 WebP 的,反之则不支持):

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

参考

  • HTMLCanvasElement.toDataURL()
  • Detect WEBP Support with JavaScript
  • 探究 WebP 一些事儿
退出移动版