一键生成sprite(雪碧图)以及 动态加载1X &2X&3X 图片

一.  为什么要使用sprite (雪碧图)

二. CSS雪碧图原理及应用

三. 生成雪碧图的三种实现方式 

一.为什么要使用雪碧图

在开发过程中,我们需要用到很多图标,这些图标的大小不是很大,但是每次需要向服务器发送请求,从而加重服务器的负担,尤其是当网站处于高访问量的情况下或网络不稳定的时候,服务器性能会明显下降。这种情况不符合被广泛遵循的雅虎军规“尽量减少HTTP请求数”的要求

例如  当我们引入如图的4个各不到1k的小图片还占用了4个请求,这显然非常浪费服务器资源

二.CSS雪碧图原理及应用

1.css方法是将小图标和背景图像合并到一张图片上,这样每个元素都会以该合成图为背景,而且页面也只加载一张合成图

然后利用CSS的背景定位(background-position)来显示需要显示的图片部分。

其中要用到 background-image,background-position

其中如下图  背景图 左上角默认和容器框重合的,现在也就是默认会显示 第一个图片 ,现在想要显示第二个图片  就需要把background-image 左移动一个(也即是X轴负方向) 所以显示的{x:-60px;y:0px}

preview

合并图片 方法有很多,图片合并软件  , 在线合并 以及 glup   webpack工具

方法一
这里提供一个很好用的在线的图片合并网站 
http://csssprites.com/可以根据自己的需要添加边距等等,还会生成对应的参考css  如图 

使用时候直接引入css 文件 ,定义好对应类名  即可
<div className='icon bg-icon1'></div>
<div className='icon bg-icon2'></div>
<div className='icon bg-icon3'></div>

 方法二  目前大多数前端项目都采用 webpack打包   同时可以使用webpack-spritesmith 插件

       主要用到:

  • webpack
  • webpack-spritesmith插件
  • file-loader 
  • sass-loader (因为 webpack-spritesmith 除了生成雪碧图之外,还会生成相应的 mixin ,使用起来很方便,所以要用 sass )

 webpack配置如下

const path = require('path');
const SpritesmithPlugin = require('webpack-spritesmith');

module.export = {
    // ...
    module: {
        rules: [
            {
                test: /png$/
                loader:[
                    'file-loader?name=i/[hash].[ext]'
                ]
            },
            {
                test: /\.(css|scss)$/,
                use: ExtractTextPlugin.extract({
                    fallback: 'style-loader',
                    use: ['css-loader', 'postcss-loader', 'sass-loader']
                })
            }
        ]
    },

    resolve: {
        modules: [
            'node_modules',
            'assets' //css在哪里能找到sprite图   文件夹的名字
        ]
    },

    plugins: [
        new SpritesmithPlugin({
            src: {
                cwd: path.resolve(__dirname, 'src/ico'),  //准备合并成sprit的图片存放文件夹
                glob: '*.png'  //哪类图片
            },
            target: {
                image: path.resolve(__dirname, 'src/assets/sprites.png'),  // sprite图片保存路径
                css: path.resolve(__dirname, 'src/assets/_sprites.scss')  // 生成的sass保存在哪里(也可以后缀改成.css 直接生成css文件,在文件中直接使用对应的类名即可)
            },
            apiOptions: {
                cssImageRef: "sprite.png" //css根据该指引找到sprite图
            }
        })
    ]
}

注:这是纯webpack的配置的情况  , 现在很多项目才用create-reactp-app 方式创建的 ,上面配置的中rules 部分已经嵌入,可以省略。

下面执行npm start  命令  会在sprite文件夹生成 sprite.png   sprite.scss 

除了 对应的数据外,sass文件中自动生成 mixin  如下

//webpack 自动生成的scss文件

$icon1-name: 'icon1';
$icon1-x: 0px;
$icon1-y: 0px;
$icon1-offset-x: 0px;
$icon1-offset-y: 0px;
$icon1-width: 32px;
$icon1-height: 32px;
$icon1-total-width: 158px;
$icon1-total-height: 32px;
$icon1-image: '../sprite/sprite.png';
$icon1: (0px, 0px, 0px, 0px, 32px, 32px, 158px, 32px, '../sprite/sprite.png', 'icon1', );

//数据略...


@mixin sprite($sprite) {
  @include sprite-image($sprite);
  @include sprite-position($sprite);
  @include sprite-width($sprite);
  @include sprite-height($sprite);
}

 在 自己的sass文件中  如下引用  就可以快乐的使用了 ,

//直接在页面中引入的scss文件

@import '../sprite/sprite.scss';

//生成的尺寸默认是原图大小  如何动态的缩放图片  如下 

@mixin spriteScale($sprite,$scale) {

  $spriteScaled: ();
  $scaleItems: (3, 4, 5, 6, 7, 8);

  @for $i from 1 through length($sprite) {
    $item: nth($sprite, $i);
    @if (null != index($scaleItems, $i)) {
      $spriteScaled: append($spriteScaled, $item * $scale);
    } @else {
      $spriteScaled: append($spriteScaled, $item);
    }
  }
  @include sprite($spriteScaled);
  background-size: nth($spriteScaled, 7) nth($spriteScaled, 8);
}

//注释: spriteScale 把雪碧图位置以及size涉及的尺寸 scale同样的倍数


@mixin sprite_dynamic ($arg1,$arg2,$scale){
  @include spriteScale($arg1 ,$scale)
  @media (-webkit-min-device-pixel-ratio:3),(min-device-pixel-ratio: 3){
    @include spriteScale($arg2 ,$scale)

    }
}


注释:sprite_dynamic 通过@media查询 ,加载2X图或者3X ,$arg1 $arg2,$scale 分别是 2X 3X图变量名  缩放倍率,具体用法如下


.icon1{
  @include sprite_dynamic($wifi_2X,$wifi_3X ,1);
}

注释 :最后在需要的类里面引用  $wifi_2x $window_3X

保存刷新页面 ,图片有显示了,但是此时network一个图片请求都没有了,在看element  dom节点,webpack  把背景图片转码为base64 

 这样以后添加 或者去掉一个图标,只更改少量代码,运行npm runbuild  或者npm start 就ok 的

 动态加载 2X &3X图  原理如下 动态加载2X&3X

发布了16 篇原创文章 · 获赞 3 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_42317878/article/details/84203835