前端项目中的图片可处理选择

通常网页的资源来讲,图片数量或者图片体积都会在整个项目中占据极大的比重,相比较代码的处理,图片处理显得特别手段有限,可是利用的好能够将用户体验提高上一个台阶css

响应式图片

根据屏幕像素加载不一样的图片尺寸,优势是自适应选择图片保持高清晰度,减小没必要要的请求渲染时间,缺点是增长代码量和项目体积.vue

媒体查询

这是兼容性最好的方法,略显繁琐node

.bg { background-image: url(demo-320w.jpg); }
@media (min-device-pixel-ratio: 2){
    .bg { background-image: url(demo-640w.jpg); }
}

srcset

以逗号分隔的一个或多个字符串列表代表一系列用户代理使用的可能的图像。每个字符串由如下组成:webpack

  1. 指向图像的 URL。
  2. 可选地,再加一个空格以后,附加如下的其一:git

    • 一个宽度描述符,这是一个正整数,后面紧跟 'w' 符号。该整数宽度除以sizes属性给出的资源(source)大小来计算获得有效的像素密度,即换算成和x描述符等价的值。
    • 一个像素密度描述符,这是一个正浮点数,后面紧跟 'x' 符号。
<img srcset="demo-320w.jpg,
             demo-480w.jpg 1.5x,
             demo-640w.jpg 2x"
     src="demo-default.jpg">

根据不一样的像素密度加载不一样的图片,都不符合的状况下会使用src做为默认图,这是用于像素密度的适配github

sizes

表示资源大小的、以逗号隔开的一个或多个字符串。每个资源大小包括:web

  1. 一个媒体条件。最后一项必定是被忽略的。
  2. 一个资源尺寸的值。
<img srcset="demo-320w.jpg,
             demo-480w.jpg 1.5x,
             demo-640w.jpg 2x"
     sizes="(max-width: 640px) 100vw,
            (max-width: 1080px) 33vw,
     src="demo-default.jpg">

表示图片在640px及如下100%宽度,超过640px但1080px及如下33%宽度,这是用于屏幕宽度的适配 算法

下面是这两个属性的兼容图api

srcset.png

picture + source

若是想要更加精确控制的话可使用这两个新标签浏览器

<picture>
  <source media="(max-width: 640px)" srcset="vertical.jpg">
  <source media="(min-width: 641px)" srcset="horizontal.jpg">
  <img src="default.jpg">
</picture>

media就至关于上面的sizes,这会从上往下判断直到加载符合的资源.

source还有一个type属性用于加载不一样的图片类型

<picture>
  <source type="image/svg" srcset="default.svg">
  <source type="image/webp" srcset="default.webp">
  <img src="default.jpg">
</picture>

下面是兼容性
picture.pngsource.png

tinypng压缩

通常这一步应该是由Ui设计负责输给到开发,也不排除部分UI没有作这一步,咱们本身也能够去作处理.

打开https://tinypng.com/选择图片...

压缩效率

从图片能够看到根据以前图片算法不一样能够压缩的体积也不同,我随便拿了两张图片测试就达到了10%67%.
0.png

对比

例子 格式 处理前 处理后 新旧体积比
图一 jpg 189.3KB 165KB 87.1%
图二 png 390KB 127KB 32.5%

未处理图
1.png

跟原图相比较,肉眼看不出画质有损害
1_1.png

未处理图
2.jpg

处理图
2_1.jpg

imagemin-webpack-plugin

利用webpack插件对项目图片进行压缩处理,基本配置

import ImageminPlugin from 'imagemin-webpack-plugin'
import imageminMozjpeg from 'imagemin-mozjpeg'

module.exports = {
  plugins: [
    new ImageminPlugin({
      plugins: [
        imageminMozjpeg({
          quality: 65,
          progressive: true // 可将图片转成渐进式渲染,用户体验较好,可是渲染耗时更久
        })
      ]
    })
  ]
}

对比

例子 格式 处理前 处理后 新旧体积比
图一 jpg 189.3KB 162KB 85.5%
图二 png 390KB 94.2KB 24.1%

原图
1.png

处理图
1_2.png

原图
2.jpg

处理图94.2KB,比上面压缩工具更优秀,画质依然看不太出区别
2_2.jpg

webP

WebP最初在2010年发布,目标是减小文件大小,但达到和JPEG格式相同的图片质量,但愿可以减小图片档在网络上的发送时间。2011年11月8日,Google开始让WebP支持无损压缩和透明色(alpha通道)的功能,而在2012年8月16日的参考实作libwebp 0.2.0中正式支持。根据Google较早的测试,WebP的无损压缩比网络上找到的PNG档少了45%的文件大小,即便这些PNG档在使用pngcrush和PNGOUT处理过,WebP仍是能够减小28%的文件大小。
webp.png

从安卓4.2开始也支持,只要兼容代码写得好也足以让项目体积大大减小,safari暂时还不支持,可是也有手段能够支持.

对比

例子 格式 处理前 处理后 新旧体积比
图一 jpg 189.3KB 116KB 61.2%
图二 png 390KB 165KB 42.3%

(不知道为何没有办法上传webp,因此就不放对比图了)

CDN图片处理

CDN除了缓存资源之外,还提供了不少额外处理工具,例如图片转换
cdn.png

这是一种更完善的方案,花钱解决各类处理保存转换的难度和工做量,具体API大同小异.

雪碧图

将多个图片合并成一张大图,能够用一个请求拿到所需的图片,而且合并后的体积比合并前的整体积还小,缺点是只能使用背景而且须要定位位置,也能够经过一些插件自动生成样式.

在线生成sprite-generator

sprites.png

这种很是智能并且方便,可是不适用长期维护或者改动频繁的项目

webpack-spritesmith

Webpack plugin that converts set of images into a spritesheet and SASS/LESS/Stylus mixins, using spritesmith and spritesheet-templates

示例配置

//webpack.config.js
var path = require('path');

var SpritesmithPlugin = require('webpack-spritesmith');

module.exports = {
    // ...
    module: {
        rules: [
            {test: /\.styl$/, use: [
                'style-loader',
                'css-loader',
                'stylus-loader'
            ]},
            {test: /\.png$/, use: [
                'file-loader?name=i/[hash].[ext]'
            ]}
        ]
    },
    resolve: {
        modules: ["node_modules", "spritesmith-generated"]
    },
    plugins: [
        new SpritesmithPlugin({
            src: {
                cwd: path.resolve(__dirname, 'src/ico'),
                glob: '*.png'
            },
            target: {
                image: path.resolve(__dirname, 'src/spritesmith-generated/sprite.png'),
                css: path.resolve(__dirname, 'src/spritesmith-generated/sprite.styl')
            },
            apiOptions: {
                cssImageRef: "~sprite.png"
            }
        })
    ]
    // ...
};

在项目开发中直接配置webpack会更加方便,更多配置可查看仓库

base64

用webpack的基本入门库能够简单实现, url-loader 功能相似于 file-loader,可是在文件大小(单位 byte)低于指定的限制时,能够返回一个 DataURL。

module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192
            }
          }
        ]
      }
    ]
  }
}

只适用于小图片的转换,原理就是经过增长代码量来减小资源请求,因此控制转换的体积限制尤其重要,并且自己的问题也很多

例子

base64.png

优势:

  • 减小资源请求数
  • 不受浏览器并发数限制没有没必要要的阻塞时间
  • 浏览器兼容性好

缺点:

  • 编码体积是原数据体积的4/3左右,且大量使用下降代码可观性
  • 浏览器不会缓存Data URL图片
  • CPU资源更多
  • 内存消耗更大
  • 渲染耗时更长

SVG

svg.png

与其余图像格式相比,使用 SVG 的优点在于:

  • SVG 可被很是多的工具读取和修改(好比记事本)
  • SVG 与 JPEG 和 GIF 图像比起来,尺寸更小,且可压缩性更强。
  • SVG 是可伸缩的
  • SVG 图像可在任何的分辨率下被高质量地打印
  • SVG 可在图像质量不降低的状况下被放大
  • SVG 图像中的文本是可选的,同时也是可搜索的(很适合制做地图)
  • SVG 能够与 Java 技术一块儿运行
  • SVG 是开放的标准
  • SVG 文件是纯粹的 XML

Vue项目引入

建立SvgIcon组件

<template>
  <svg :class="svgClass" aria-hidden="true">
    <use :xlink:href="iconName"></use>
  </svg>
</template>

<script>
export default {
  name: 'svg-icon',
  props: {
    iconClass: {
      type: String,
      required: true
    },
    className: {
      type: String
    }
  },
  computed: {
    iconName() {
      return `#icon-${this.iconClass}`
    },
    svgClass() {
      if (this.className) {
        return 'svg-icon ' + this.className
      } else {
        return 'svg-icon'
      }
    }
  }
}
</script>

<style scoped>
.svg-icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}
</style>

建立icons文件夹

import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'// svg组件

// 注册到全局
Vue.component('svg-icon', SvgIcon)

const requireAll = requireContext => requireContext.keys().map(requireContext)
// eslint-disable-next-line
const req = require.context('./svg', false, /\.svg$/)
requireAll(req)

在main.js中引入

import './icons'

使用

<svg-icon icon-class="user" />

SVG sprite loader

Webpack loader for creating SVG sprites.

{
    test: /\.svg$/,
    loader: 'svg-sprite-loader',
    include: [resolve('src/icons')],
    options: {
        symbolId: 'icon-[name]'
    }
}
-------------------------------------------
exclude: [resolve('src/icons')],

SVG在线压缩合并工具

具体参考张鑫旭博客SVG精简压缩工具svgo简介和初体验

字体图标

上面说的全部方式终究仍是图片或者会有某些损耗,而字体图标是以字体形式展现图标

阿里矢量图标库

iconfont.png

应用代码有几种,目前官方推荐方式是

unicode引用

unicode是字体在网页端最原始的应用方式,特色是:

  • 兼容性最好,支持ie6+,及全部现代浏览器。
  • 支持按字体的方式去动态调整图标大小,颜色等等。
  • 可是由于是字体,因此不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。

第一步:拷贝项目下面生成的font-face

@font-face {font-family: 'iconfont';
    src: url('iconfont.eot');
    src: url('iconfont.eot?#iefix') format('embedded-opentype'),
    url('iconfont.woff') format('woff'),
    url('iconfont.ttf') format('truetype'),
    url('iconfont.svg#iconfont') format('svg');
}

第二步:定义使用iconfont的样式

.iconfont{
    font-family:"iconfont" !important;
    font-size:16px;font-style:normal;
    -webkit-font-smoothing: antialiased;
    -webkit-text-stroke-width: 0.2px;
    -moz-osx-font-smoothing: grayscale;}

第三步:挑选相应图标并获取字体编码,应用于页面

<i class="iconfont">&#x33;</i>

font-class引用

font-class是unicode使用方式的一种变种,主要是解决unicode书写不直观,语意不明确的问题。

与unicode使用方式相比,具备以下特色:

  • 兼容性良好,支持ie8+,及全部现代浏览器。
  • 相比于unicode语意明确,书写更直观。能够很容易分辨这个icon是什么。
  • 由于使用class来定义图标,因此当要替换图标时,只须要修改class里面的unicode引用。
  • 不过由于本质上仍是使用的字体,因此多色图标仍是不支持的。

第一步:拷贝项目下面生成的fontclass代码:

//at.alicdn.com/t/font_8d5l8fzk5b87iudi.css

第二步:挑选相应图标并获取类名,应用于页面:

<i class="iconfont icon-xxx"></i>

symbol引用

这是一种全新的使用方式,应该说这才是将来的主流,也是平台目前推荐的用法。相关介绍能够参考这篇文章 这种用法实际上是作了一个svg的集合,与上面两种相比具备以下特色:

  • 支持多色图标了,再也不受单色限制。
  • 经过一些技巧,支持像字体那样,经过font-size,color来调整样式。
  • 兼容性较差,支持 ie9+,及现代浏览器。
  • 浏览器渲染svg的性能通常,还不如png。

第一步:拷贝项目下面生成的symbol代码:

//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js

第二步:加入通用css代码(引入一次就行):

<style type="text/css">
    .icon {
       width: 1em; height: 1em;
       vertical-align: -0.15em;
       fill: currentColor;
       overflow: hidden;
    }
</style>

第三步:挑选相应图标并获取类名,应用于页面:

<svg class="icon" aria-hidden="true">
    <use xlink:href="#icon-xxx"></use>
</svg>

懒加载

这个是比较老生常谈的手段了,从JQ时代开始就已经有比较丰富的经验,到了框架时代,若是用Vue的话我知道的就有

vue-lazyload

功能比较强大

  • 轻量级、强大且易于使用
  • 可做用在任何类型的图像
  • 在加载图像时添加加载类
  • 同时支持Vue 1.0和Vue 2.0

引入模块

import Vue from 'vue'
import App from './App.vue'
import VueLazyload from 'vue-lazyload'

Vue.use(VueLazyload)

// or with options
Vue.use(VueLazyload, {
  preLoad: 1.3,
  error: 'dist/error.png',
  loading: 'dist/loading.gif',
  attempt: 1
})

new Vue({
  el: 'body',
  components: {
    App
  }
})

使用方法

可自定义加载和错误图

<div v-lazy-container="{ selector: 'img', error: 'xxx.jpg', loading: 'xxx.jpg' }">
  <img data-src="//domain.com/img1.jpg">
  <img data-src="//domain.com/img2.jpg">
  <img data-src="//domain.com/img3.jpg">  
</div>
// 或者
<div v-lazy-container="{ selector: 'img' }">
  <img data-src="//domain.com/img1.jpg" data-error="xxx.jpg">
  <img data-src="//domain.com/img2.jpg" data-loading="xxx.jpg">
  <img data-src="//domain.com/img3.jpg">  
</div>

预加载

一次性加载完图片再开始渲染界面

简单实现

<script>
export default {
  data () {
    return {
      count: 0,
    }
  },
  mounted: function() {
    this.preload()
  },
  methods: {
    preload: function() {
      const imgs = ['xxx.png', ...]

      for (let img of imgs) {
        const image = new Image()
        image.src = img
        image.onload = () => {
          this.count++
        }
      }

    },
  },
}
</script>
相关文章
相关标签/搜索