关于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