H5、小程序使用 webp 格式图片,如何判断环境是否支持

H5、小程序使用 webp 格式图片,如何判断环境是否支持

最近我在做 H5、小程序的性能优化,其中一项优化,是把 H5、小程序的 jpg、png 图片转换为 webp 格式的图片,这是因为相比 jpg、png,webp 格式的图片体积更小、传输速度更快。

转换方法很简单,现在各大云服务商基本都提供了方法,比如 腾讯云 只需要在图片 CDN 链接后面拼接一些参数:

不过我还是遇到了些小麻烦,从 can I use 查询发现,目前还有少部分浏览器不支持 webp。H5 使用 webp 格式图片时,我需要做一些兼容。

H5、小程序使用 webp 格式图片,如何判断环境是否支持

至于微信小程序使用 webp 格式图片,也需要我再琢磨琢磨。微信官方文档 虽然说基础库 2.9.0 之上支持 webp,但微信的文档一向不太靠谱,我不能完全信任它。

一番研究后,我知道了判断环境支持 webp 的几种办法。对这些办法的优劣,我也有自己的观点,于是我便整理了这篇文章。

拳打 H5,脚踢小程序。我是「小霖家的混江龙」,关注我,带你了解更多实用的 H5、小程序武学。

toDataURL(‘image/webp’)

代码

第一种 H5 的判断方法,其实是判断 H5 能不能利用 canvas 的 toDataURL() API 得到一张 webp 图片。

function isWebpSupported() {
  try {
    return document.createElement('canvas')
      .toDataURL('image/webp')
      .indexOf('data:image/webp') === 0
  } catch (e) {
    return false
  }
}

原理

这种方法原理是啥呢?我们可以继续在 Can I use 查询 toDataURL('image/webp') 的兼容性。

H5、小程序使用 webp 格式图片,如何判断环境是否支持

可以看到,兼容 toDataURL('image/webp') 的浏览器、是兼容 webp 浏览器的子集。

H5、小程序使用 webp 格式图片,如何判断环境是否支持

换句话说,这是一种「宁杀错一百,也不放过一个」的方法。举 Safari 浏览器为例子,它其实是可以展示 webp 图片的,但它会被这种 toDataURL('image/webp') 方法误伤。

H5、小程序使用 webp 格式图片,如何判断环境是否支持

优缺点

这种方法的优缺点如下:

  • 优点:代码短小,且方法是同步的,容易理解
  • 缺点:误伤性太高,iOS 的 Safari 浏览器被全部误伤。

微信小程序能用吗

这种判断方法微信小程序可以使用吗?很遗憾不可以。

我们之所以用 toDataURL('image/webp') 判断 H5 能不能使用 webp,前提是我们知道 兼容 toDataURL('image/webp') 的浏览器、是兼容 webp 浏览器的子集

但我在微信官方文档中,没有看到类似 canvas 的 toDataURL(‘image/webp’) 是 webp 子集的描述。基于此,我判断微信小程序不能用这个方法。

加载一张 webp 图片试试,看会不会出错

代码

第二种 H5 的判断方法,是直接异步加载一张 webp 格式的图片。如果加载成功,证明环境能支持 webp;如果加载失败,证明环境不支持 webp。

function isWebpSupported() {
  if (!Image) {
    return Promise.resolve(false)
  }

  return new Promise((resolve) => {
    const img = new Image()
    img.onload = function () {
      resolve((img.width > 0) && (img.height > 0))
    }
    img.onerror = function () {
      resolve(false)
    }
    img.src = 'data:image/webp;base64,UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA';
  })
}

原理

这种方法来源于 Google 官方文档,webp 其实支持四个功能,无损压缩、有损压缩、透明度和动画,每个功能对应了一张 webp 图片:

function checkWebpFeature(feature, callback) {
  const kTestImages = {
    lossy: "UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA",
    lossless: "UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==",
    alpha: "UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",
    animation: "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"
  }
  const img = new Image()
  img.onload = function () {
    const result = (img.width > 0) && (img.height > 0)
    callback(feature, result)
  }
  img.onerror = function () {
    callback(feature, false)
  }
  img.src = "data:image/webp;base64," + kTestImages[feature]
}

如果对四种功能都进行判断的话,代码会变得很臃肿。所以实际开发中,基本只选择一张 webp 的图片。

Can I use 查询结果来看,浏览器要么是先支持 webp 的有损压缩,再支持 webp 的无损压缩、透明度和动画;要么是有损压缩、无损压缩、透明度和动画一起支持。因此,我们往往选择一张支持动画的 webp 图片,用它去试探浏览器是否支持 webp 格式。

优缺点

  • 优点,安全可靠;
  • 缺点,异步加载。

微信小程序能用吗

这种方法小程序可以用吗?理论上可以,但需要进行改造。

微信官方文档上虽然提到了 createImage 方法,但我实际测试发现,这个方法竟然没了 (*  ̄︿ ̄)。

H5、小程序使用 webp 格式图片,如何判断环境是否支持

那么我们要怎么改造呢?我们不能再单独使用 js,而是需要结合 js 和 wxml。在 wxml 中手动写一个 image 标签,再给它绑定 onloadonerror 事件。虽然不太优雅,但对小程序来说,优不优雅已经不重要了,能用就很不错了。

直接判断版本

代码

第三种方法 H5 不常使用,一般是小程序使用。

function isWebpSuported() {
  try {
    const { system, SDKVersion } = wx.getSystemInfoSync()
    const [sysName, sysVersion] = (system || '').split(' ')
    if (!compareVersion(SDKVersion, '2.9.0')) {
      return false
    }

    if (
      sysName.toUpperCase() === 'ANDROID' &&
      compareVersion(sysVersion, '4.4.4')
    ) {
      return true
    }

    if (
      sysName.toUpperCase() === 'IOS' &&
      compareVersion(sysVersion, '14.0.0')
    ) {
      return true
    }

    return false
  } catch (e) {
    return false
  }
}

原理

我们已经通过 Can I use 知道:

  • Android 4.4.4 以下,iOS 14 以下的浏览器不支持 webp。

又从 微信小程序 image 组件文档 里知道:

  • 基础库版本 > 2.9.0 支持 webp。

那么干脆把所有条件都做一个组合,就得到了上述代码,其中 compareVersion()微信官方文档 中比较版本号的代码。

优点

  • 优点:同步判断。
  • 缺点:据说 Android 即便基础库版本低于 2.9.0 也是可以显示 webp 的,但我没有在官方文档上找到类似说法。可能会误伤部分 Android 手机。

总结

本文介绍了 H5、小程序使用 webp 格式图片时,判断环境是否支持的方法。

  • toDataURL('image/webp') 的方法,H5 支持,但是会误伤部分浏览器。小程序不支持。
  • 先加载一张 webp 图片的方法,H5 和小程序都支持。但小程序代码实现得不优雅。
  • 直接判断版本号的方法。H5 不常采用,小程序可以采用。但可能会误伤部分 Android 手机。

拳打 H5,脚踢小程序。我是「小霖家的混江龙」,关注我,带你了解更多实用的 H5、小程序武学。

原文链接:https://juejin.cn/post/7347161048573558799 作者:小霖家的混江龙

(0)
上一篇 2024年3月18日 下午4:23
下一篇 2024年3月18日 下午4:33

相关推荐

发表回复

登录后才能评论