關於css sprites(雪碧圖/精靈圖)的幾種實現方案能夠參考淺談 CSS Sprites 雪碧圖應用。本文主要討論基於webpack的css sprites實現方案。css
因爲使用webpack時會涉及到其餘插件,沒有相關基礎的能夠參考我以前的一篇文章使用Webpack對CSS文件進行後處理先進行配置,不過目錄結構和該篇會有點差異。html
+ node_modules + src // 開發目錄 + images + icon ..png ..png + js + main.js + dist // 代碼產出目錄 – index.html + js - bundle.js + css - sprite.css - sprite.json + images - sprite.png – package.json – package-lock.json – webpack.config.js
npm install webpack-spritesmith --save-dev
var SpritesmithPlugin = require('webpack-spritesmith'); // 生成的雪碧圖CSS文件模板自定義,也能夠不配置直接使用默認的模板 var templateFunction = function (data) { // PC端配置 var shared = '.ico { diaplay: inline-block; background-image: url(I); background-size: Dpx Hpx; }' .replace('I', data.sprites[0].image) .replace('D', data.sprites[0].total_width) .replace('H', data.sprites[0].total_height); var perSprite = data.sprites.map(function (sprite) { return '.ico-N { width: Wpx; height: Hpx; background-position: Xpx Ypx; }' .replace('N', sprite.name.replace(/_/g, '-')) .replace('W', sprite.width) .replace('H', sprite.height) .replace('X', sprite.offset_x) .replace('Y', sprite.offset_y); }).join('\n'); // 移動端配置 var sharedRem = '.ico { diaplay: inline-block; background-image: url(I); background-size: Drem Hrem; }' .replace('I', data.sprites[0].image) .replace('D', data.sprites[0].total_width / 100) .replace('H', data.sprites[0].total_height / 100); var perSpriteRem = data.sprites.map(function (sprite) { return '.ico-N { width: Wrem; height: Hrem; background-position: X Yrem; }' .replace('N', sprite.name.replace(/_/g, '-')) .replace('W', sprite.width / 100) .replace('H', sprite.height / 100) .replace('X', sprite.offset_x / 100) .replace('Y', sprite.offset_y / 100); }).join('\n'); return shared + '\n' + perSprite + '\n\n' + sharedRem + '\n' + perSpriteRem; }; ... ... plugins: [ new SpritesmithPlugin({ src: { cwd: path.resolve(__dirname, 'src/images/icon'), // 圖標根路徑 glob: '*.png' // 圖標類型 }, target: { image: path.resolve(__dirname, 'dist/images/sprite.png'), // 生成雪碧圖的名稱和路徑 css: [ [path.resolve(__dirname, 'dist/css/sprite.css'), { // 生成CSS文件的名稱和路徑 format: 'function_based_template' // 模板配置,注意在customTemplates中配置對應名稱的屬性名 }], [path.resolve(__dirname, 'dist/css/sprite.json'), { // 生成json文件的名稱和路徑,想看圖片數據的能夠配置該項 format: 'json_texture' }] ] }, customTemplates: { 'function_based_template': templateFunction // 上一項使用到的模板變量 }, apiOptions: { cssImageRef: '../images/sprite.png' // 生成的CSS中引用的雪碧圖路徑 }, spritesmithOptions: { algorithm: 'top-down', // 生成的雪碧圖圖標排列方式 padding: 1 // 圖標的間隔 } }), new SpritesmithPlugin... //若是須要生成不止一張雪碧圖則繼續配置 ],
Spritesmith.processImages - old // Add our images to our canvas (dry run) images.forEach(function (img) { // Save the non-padded properties as meta data var width = img.width; var height = img.height; var meta = {img: img, actualWidth: width, actualHeight: height}; // Add the item with padding to our layer layer.addItem({ width: width + padding, height: height + padding, meta: meta }); }); - new // Add our images to our canvas (dry run) images.forEach(function (img) { // Save the non-padded properties as meta data var width = img.width; var height = img.height; var meta = {img: img, actualWidth: width, actualHeight: height}; // chauncywu // 用戶傳入圖標間隔參數padding,規定兩個圖標的間隔至少爲padding,而後下一個圖標的位置以10爲倍數的位置開始 // eg.圖標1高度爲96px,加上padding: 2px,那麼圖標2的開始位置爲96+2=98,而後取整即100px,從100px位置開始 var layerWidth = width + padding; var layerHeight = height + padding; if(layerWidth%10 != 0) { layerWidth = Math.ceil(layerWidth/10) * 10; } if(layerHeight%10 != 0) { layerHeight = Math.ceil(layerHeight/10) * 10; } // Add the item with padding to our layer layer.addItem({ width: layerWidth, height: layerHeight, meta: meta }); });
webpack --mode development
在研究雪碧圖的過程當中也有在思考在項目中雪碧圖的必要性,常常看到網上說HTTP/2即將到來,壓縮代碼、文件合併、雪碧圖都是多餘的操做,可是看到這篇文章HTTP/2 下提升網站加載速度的資源打包指南,結論是:儘管 HTTP/2 被設計成一個能夠高效傳輸許多小文件的協議,但當須要傳輸的文件數達到必定規模後,每一個文件帶來的額外開銷也會聚沙成塔,影響效率。因此至少在還有很長一段的時間內雪碧圖仍是頗有必要的。node