通过vue指令和函数实现对商品图片的适配压缩

背景

在一些多图应用场景(电商、活动等)中,会存在图片没有压缩,导致加载变慢的场景。

同时在lighthouse跑分中,如果图片尺寸没有与承载容器尺寸相匹配也会影响到页面的加载速度和分数。

当后端无法精细化处理的时候,就需要前端针对当前场景进行处理了。

方案

以下对阿里云oss、七牛、京东的图片来源地址进行了处理

调研

来源 处理方式 案例(原链接|调整后链接) 备注
京东 尺寸:
jfs → s220x220_jfs
更改图片质量:!q74.dpg
https://img11.360buyimg.com/sku/jfs/t11383/145/2869635527/732077/6eef8592/5cda2c95Nf943ef20.jpg

https://img11.360buyimg.com/sku/s360x360_jfs/t11383/145/2869635527/732077/6eef8592/5cda2c95Nf943ef20.jpg!q75.dpg
偶现,部分图片跳帧·处理后,会请求不到京东图片比较特殊
七牛 尺寸:
/thumbnail/220x220
质量:/quality/75
渐进显示:/interlace/1
格式:format/jpg
https://demo.qiniu.com/FpeyGLFzQ2MLTy0_uf1Fh64Pz7ZE
https://demo.qiniu.com/FpeyGLFzQ2MLTy0_uf1Fh64Pz7ZE?imageMogr2/thumbnail/220x220/quality/75/interlace/1
七牛文档七牛通过imageMogr2可直接调整图片渐进显示只支持jpg
腾讯云 尺寸:
/thumbnail/220x220
质量:/quality/75
渐进显示:/interlace/1
格式:format/jpg
https://demo.tencent.net/error.ac4119ee.png
https://demo.tencent.net/error.ac4119ee.png?imageMogr2/thumbnail/220x220/quality/75/interlace/1
腾讯云文档

优化点

  • 调整图片尺寸
  • 修改图片格式webp or png
  • jpg开启渐进显示
  • 调整图片质量

实现

综合以上,可实现以下vue指令和函数。以下为主要的代码实现
目前代码已上传至CSDN,可直接下载

export const imgMogr = function(url, option = {}) {
  const cdnType = getCdnType(url);
  url = replaceProtocol(url);
  if (!cdnType) return url;
  let { w, h, f } = option;
  if (w) {
    w = w * 2;
  }
  if (h) {
    h = h * 2;
  }

  if (canUseWebp()) f = 'webp';
  const sizeBoth = w && h;
  const sizeMaybe = w || h;
  return {
    ali() {
      return [
        url,
        '?x-oss-process=image/quality,q_70/interlace,1',
        f ? `/format,${f}` : '',
        sizeMaybe
          ? `/resize,${w ? 'w_' + w : ''}${sizeBoth ? ',' : ''}${h ? 'h_' + h : ''},m_fixed`
          : ''
      ].join('');
    },
    qiniu() {
      return [
        url,
        '?imageMogr2/quality/70/interlace/1',
        f ? `/format/${f}` : '',
        sizeMaybe
          ? `/thumbnail/${w || ''}${sizeBoth ? 'x' : ''}${h || ''}${sizeBoth ? '!' : ''}`
          : ''
      ].join('');
    },
    jd() {
      return [
        w && h ? url.replace('jfs', `s${w}x${h}_jfs`) : url,
        '!q70.dpg',
        f === 'webp' ? '.webp' : ''
      ].join('');
    }
  }[cdnType]();
};

API

Constants

checkWebp ⇒ Promise
imgMogr ⇒ *
imgMogrDirective
imgMogrVue

Functions

replaceProtocol(str) ⇒ string
getCdnType(url, checkProceed) ⇒ string | boolean
canUseWebp() ⇒ boolean
handleTagType(el, binding, vnode, reset)

checkWebp ⇒ Promise

Kind: global constant
Returns: Promise - Promise
Description:: 检测是否支持 webp
Example::

checkWebp() => Promise

Example::

checkWebp().then(res => console.log(res)) => true

imgMogr ⇒ *

Kind: global constant
Returns: * - 压缩后的图片地址
Description:: 图片压缩,
数组 join 拼接 [url,基础压缩,格式转换,尺寸压缩].join(‘’)
京东的特殊
Example::

imgMogr('', {w: 100, h: 100, f: 'webp'}) => ''
Param Type Description
url * 图片地址
option * 压缩参数

imgMogrDirective

Kind: global constant
Description:: 图片处理指令
Example::

<img v-imogr="{w: 100, h: 100, f: 'webp'}" src="https://www.xxxx.com/xxx.jpg" />
Param Type Description
el * 指令所绑定的元素,可以用来直接操作 DOM
binding * 指令的绑定对象
vnode * Vue 编译生成的虚拟节点

imgMogrVue

Kind: global constant
Description:: 图片处理指令
Example::

<img v-imogr="{w: 100, h: 100, f: 'webp'}" src="https://www.xxxx.com/xxx.jpg" />

Example::

this.$imogr('', {w: 100, h: 100, f: 'webp'}) => ''

Example::

<img src="'https://www.xxxx.com/xxx.jpg' | imgMogr" />
Param Type Description
el * 指令所绑定的元素,可以用来直接操作 DOM
binding * 指令的绑定对象
vnode * Vue 编译生成的虚拟节点

replaceProtocol(str) ⇒ string

Kind: global function
Description:: 替换 http 为 https
Example::

replaceProtocol('') => ''
Param Type
str string

getCdnType(url, checkProceed) ⇒ string | boolean

Kind: global function
Returns: string | boolean - cdn 类型
Description:: 通过 url 检测 cdn 类型, 已处理的会返回 false
Example::

getCdnType('') => 'ali'
Param Type Default Description
url string 图片地址
checkProceed boolean true 是否检测已处理过的

canUseWebp() ⇒ boolean

Kind: global function
Returns: boolean - 是否支持 webp
Description:: 从本地存储中获取是否支持 webp
Example::

canUseWebp() => true

handleTagType(el, binding, vnode, reset)

Kind: global function
Description:: 处理标签类型

Param Type Description
el * 指令所绑定的元素,可以用来直接操作 DOM
binding * 指令的绑定对象
vnode * Vue 编译生成的虚拟节点
reset * 是否重置

你可能感兴趣的:(vue.js,前端,javascript)