通常網頁的資源來講,圖片數量或者圖片體積都會在整個項目中佔據極大的比重,相比較代碼的處理,圖片處理顯得特別手段有限,可是利用的好能夠將用戶體驗提高上一個臺階css
根據屏幕像素加載不一樣的圖片尺寸,優勢是自適應選擇圖片保持高清晰度,減小沒必要要的請求渲染時間,缺點是增長代碼量和項目體積.vue
這是兼容性最好的方法,略顯繁瑣node
.bg { background-image: url(demo-320w.jpg); } @media (min-device-pixel-ratio: 2){ .bg { background-image: url(demo-640w.jpg); } }
以逗號分隔的一個或多個字符串列表代表一系列用戶代理使用的可能的圖像。每個字符串由如下組成:webpack
可選地,再加一個空格以後,附加如下的其一: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
表示資源大小的、以逗號隔開的一個或多個字符串。每個資源大小包括:web
<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
若是想要更加精確控制的話可使用這兩個新標籤瀏覽器
<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>
下面是兼容性
通常這一步應該是由Ui設計負責輸給到開發,也不排除部分UI沒有作這一步,咱們本身也能夠去作處理.
從圖片能夠看到根據以前圖片算法不一樣能夠壓縮的體積也不同,我隨便拿了兩張圖片測試就達到了10%和67%.
例子 | 格式 | 處理前 | 處理後 | 新舊體積比 |
---|---|---|---|---|
圖一 | jpg | 189.3KB | 165KB | 87.1% |
圖二 | png | 390KB | 127KB | 32.5% |
未處理圖
跟原圖相比較,肉眼看不出畫質有損害
未處理圖
處理圖
利用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% |
原圖
處理圖
原圖
處理圖94.2KB,比上面壓縮工具更優秀,畫質依然看不太出區別
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%的文件大小。
從安卓4.2開始也支持,只要兼容代碼寫得好也足以讓項目體積大大減小,safari暫時還不支持,可是也有手段能夠支持.
例子 | 格式 | 處理前 | 處理後 | 新舊體積比 |
---|---|---|---|---|
圖一 | jpg | 189.3KB | 116KB | 61.2% |
圖二 | png | 390KB | 165KB | 42.3% |
(不知道爲何沒有辦法上傳webp,因此就不放對比圖了)
CDN除了緩存資源之外,還提供了不少額外處理工具,例如圖片轉換
這是一種更完善的方案,花錢解決各類處理保存轉換的難度和工做量,具體API大同小異.
將多個圖片合併成一張大圖,能夠用一個請求拿到所需的圖片,而且合併後的體積比合並前的整體積還小,缺點是隻能使用背景而且須要定位位置,也能夠經過一些插件自動生成樣式.
這種很是智能並且方便,可是不適用長期維護或者改動頻繁的項目
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會更加方便,更多配置可查看倉庫
用webpack的基本入門庫能夠簡單實現, url-loader 功能相似於 file-loader,可是在文件大小(單位 byte)低於指定的限制時,能夠返回一個 DataURL。
module.exports = { module: { rules: [ { test: /\.(png|jpg|gif)$/, use: [ { loader: 'url-loader', options: { limit: 8192 } } ] } ] } }
只適用於小圖片的轉換,原理就是經過增長代碼量來減小資源請求,因此控制轉換的體積限制尤其重要,並且自己的問題也很多
與其餘圖像格式相比,使用 SVG 的優點在於:
<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>
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)
import './icons'
<svg-icon icon-class="user" />
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精簡壓縮工具svgo簡介和初體驗
上面說的全部方式終究仍是圖片或者會有某些損耗,而字體圖標是以字體形式展現圖標
應用代碼有幾種,目前官方推薦方式是
unicode是字體在網頁端最原始的應用方式,特色是:
第一步:拷貝項目下面生成的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">3</i>
font-class是unicode使用方式的一種變種,主要是解決unicode書寫不直觀,語意不明確的問題。
與unicode使用方式相比,具備以下特色:
第一步:拷貝項目下面生成的fontclass代碼:
//at.alicdn.com/t/font_8d5l8fzk5b87iudi.css
第二步:挑選相應圖標並獲取類名,應用於頁面:
<i class="iconfont icon-xxx"></i>
這是一種全新的使用方式,應該說這纔是將來的主流,也是平臺目前推薦的用法。相關介紹能夠參考這篇文章 這種用法實際上是作了一個svg的集合,與上面兩種相比具備以下特色:
font-size
,color
來調整樣式。第一步:拷貝項目下面生成的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的話我知道的就有
功能比較強大
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>