使用Vue + 雪碧圖(CSS sprite),webpack-spritesmith

開發了將近兩年的小程序,一直默默的在小程序迭代中。好久沒有玩過Vue, 最近有個新的項目用上了Vue, 看到Ui圖小圖標太多了, 立刻想着要用雪碧圖, 啪啦啪啦的找雪碧圖合成方法css

最後給你們推薦webpack-spritesmith , 這是一個融合node的生成css + 雪碧圖(CSS sprite)排版的工具, 能夠導入css以後,利用標籤像iconfont同樣調用便可,比較的方便vue

github: github.com/mixtur/webp…node

前言: 能夠自定義設置樣式模板,以後能夠自定義標籤,無論是stylus / scss / less / css 都能定義python

1. 什麼都不要說了,安裝吧~

npm i spritesheet-templates --save-dev
複製代碼

2. 先批量重命名圖片

爲何? 整齊好看,就像閱兵儀式同樣, 其實按順序排列,是方便你css表找更好webpack

3. 有零零碎碎的圖標庫後,就開始配置webpack

目錄結構

# 依據使用說明
/
|-src
| |-icons
| | |-icon_01.png
| | |-icon_02.png
| | |-icon_03.png
| | ...
| |-style.styl
| ...
|- 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/icons'), #圖標所在的位置 glob: '*.png' #圖標的格式 }, target: { #建議這兩個文件放一塊兒 image: path.resolve(__dirname, 'src/spritesmith-generated/sprite.png'), #生成指定位置的雪碧圖 css: path.resolve(__dirname, 'src/spritesmith-generated/sprite.[styl|css|stylus|scss|less]'), #生成指定位置樣式表,會對應雪碧圖全部的背景偏移位置 }, apiOptions: { #針對上面生成的樣式表的相對路徑sprite.[styl|css|stylus|scss|less] cssImageRef: "./sprite.png" } }) ] // ... }; 複製代碼

自定義樣式模板

第二種配置方式,通用,這種自定義樣式模板git

# 除法精度問題
function divide (arg1, arg2) {
    console.log(arg1, arg2)
    var t1 = 0; var t2 = 0; var r1; var  r2
    try { t1 = arg1.toString().split('.')[1].length } catch (e) {}   // --小數點後的長度
    try { t2 = arg2.toString().split('.')[1].length } catch (e) {}  // --小數點後的長度
    r1 = Number(arg1.toString().replace('.', ''))  // --去除小數點變整數
    r2 = Number(arg2.toString().replace('.', ''))  // --去除小數點變整數
    return (r1 / r2) * Math.pow(10, t2 - t1)   // ---整數相除 在乘上10的平方  小數點的長度
}
 
 # 函數自定義樣式表方法
 #須要特地說明: 若是你的
 function templateFunction(data) {
    var spritesheet = data.spritesheet # 精靈圖對象
    var unit = 'px' # 單位
    var w = spritesheet.width # 精靈圖寬
    var h  = spritesheet.height # 精靈圖高
    var shared = `.ico { 
          background-image: url(${spritesheet.image});
          background-size: ${w}${unit} ${h}${unit} 
    }`
    
    #循環雪碧圖而且設置對應圖標樣式的寬度與高度
    # data.sprites: 精靈圖小圖標遍歷
    var perSprite = data.sprites.map(function (sprite) {
        var offsetX = sprite.offset_x # 距離左上角的x軸距離, 這裏爲負數,已經默認算好
        var offsetY = sprite.offset_y # 距離左上角的y軸距離, 這裏爲負數,已經默認算好
        # 須要return出去,而且返回一個默認樣式,由於到了rem會有一些誤差,因此須要設置padding:1px
        return `.ico-N {position:relative; top: 2${unit};padding: 1${unit}; width: ${sprite.width}${unit}; height: ${sprite.width}${unit}; background-position: X${unit} Y${unit}; display: inline-block;}`
            .replace('N', sprite.name)
            .replace('X', offsetX)
            .replace('Y', offsetY)
    }).join('\n')

    return shared + '\n' + perSprite
}



module.exports = {
        ...
        plugins: [
            new SpritesmithPlugin({
                src: {
                    cwd: path.resolve(__dirname, 'src/icons'), #圖標所在的位置
                    glob: '*.png' #圖標的格式
                },
                target: {
                    image: path.resolve(__dirname, 'src/spritesmith-generated/sprite.png'), #生成指定位置的雪碧圖
                    css: [
                        # 引入樣式模板
                        [path.resolve(__dirname, 'src/spritesmith-generated/sprite.[styl|css|stylus|scss|less]'), {
                            format: 'function_based_template' #這裏的樣式模板經過customTemplates指定
                        }]
                    ]
                },
                apiOptions: {
                    cssImageRef: './sprite.png'
                },
                customTemplates: {
                    'function_based_template':  templateFunction, # 指定樣式模板,這裏能夠是函數,能夠是handlebars後臺模板
                },
                spritesmithOptions: {
                    #針對上面生成的樣式表的相對路徑sprite.[styl|css|stylus|scss|less]
                    algorithm: 'top-down', # 從上到下排列雪碧圖
                    padding: 20, # 雪碧圖的間距
                }
            })
        ]
}
複製代碼

4. 在標籤中使用

  • 打開你的圖標看看相應須要的圖標名稱
  • 複製你須要圖標的名稱,打開剛纔生成的sprite.[styl|css|stylus|scss|less]
  • 引入sprite.[styl|css|stylus|scss|less]到src/main.js,主目錄下 例如:
  • 在.vue - template 中使用
<div class="ico ico-icon_14"></div>
    <div class="ico ico-icon_13"></div>
    <div class="ico ico-icon_16"></div>
    <div class="ico ico-icon_17"></div>
    <div class="ico ico-icon_18"></div>
    <div class="ico ico-icon_19"></div>
    <div class="ico ico-icon_20"></div>
    <div class="ico ico-icon_21"></div>
複製代碼

這裏至關於引入你剛纔自定義樣式表中的模板 github

5. 大功告成,成功使用,很是方便

之後只須要npm run dev 啓動則自動進行生成,建議若是以後加圖,能夠分出來,或者是按須要加在後面,更好的維護web

6. 適配rem的坑

我是用750設計稿 用的75像素的 , 因此轉換成 10rem = 750px / 1rem = 75pxnpm

  • 坑1: 單位與位置轉換問題 項目中使用了 postcss-px2rem-exclude 或者一些其餘的轉換rem工具

ps: 這些工具設置以後,都會致使rem自動轉換,雪碧圖位置與樣式表提供的沒法對應上, 因此須要針對正個雪碧圖設置background-size 其實至關於,你雪碧圖多少background-size就設置多少,例如雪碧圖300px * 300px 那麼background-size: 300px 300px, 經過設置以後,就不會遇到對應不上的問題小程序

  • 坑2: 安卓-微信內部QQ瀏覽器邊邊角角會誤差1px

好好的配了半天的我,遇到這個坑,解決了差很少6-7小時,這個問題主要是由於rem轉換以後,計算值有所誤差致使的,在外部瀏覽器打開都沒問題,安卓微信內部QQ瀏覽器就出現誤差問題,用別的手機也會出現,我試圖用%代替,可是未能成功,嘗試過用精確的函數去計算精度問題。發現仍是會誤差,總的來講不知道哪一個環節出了問題。那麼,我就不糾結這些事了。

其一 在配置樣式表中加入 padding: 1px 去解決轉回的時候彌補了一些計算js存在的精度

其二就是把 配置中spritesmithOptions.padding 間距設置大一點,雪碧圖方向修改掉top-down,就解決了rem在微信內部QQ瀏覽器

spritesmithOptions: {
    #針對上面生成的樣式表的相對路徑sprite.[styl|css|stylus|scss|less]
    algorithm: 'top-down', # 從上到下排列雪碧圖
    padding: 20, # 雪碧圖的間距
}
複製代碼

總結: 已經沒法思考了...

相關文章
相關標籤/搜索