學習前端的同學注意了!!!
學習過程中遇到什麼問題或者想獲取學習資源的話,歡迎加入前端學習交流羣,羣號碼:328058344
先做一個選擇題:前端開發使用構建工具的目的是什麼?
A、因爲現在流行node.js,都在使用構建工具
B、讓前端開發變得高大上,和後端一樣編譯才能運行
C、讓自動化工具替代重複的手工操作,比如合併代碼,刷新瀏覽器預覽效果等。
選擇A、B請直接關閉此文,選擇C請繼續閱讀。
其實使用工具的目的就一個: 自動化一些重複操作,提升工作效率 。ok,明確了這一點之後再來探究有哪些方式,可以把一堆小圖標合併成一個圖片文件並生成相應的樣式。
按照生成文件和使用方式來看,可以大致分成3類處理方式:
png sprite
合成雪碧圖是歷史最悠久最成熟的解決方案,把不同的png小圖標拼接成一張png圖片。
手動操作
有的公司甚至讓UI設計師來合併小圖標(UI設計師成了自動化工具,囧~),這樣做減少前端工作量的同時也帶來一些問題。
- 溝通問題。如果只想簡單地修改某個圖標顏色,大小,都要與設計師溝通,一來一回增加時間成本。
- 樣式問題。設計師提供的小圖標不能直接用,要配合特定的樣式(偏移值,大小)才行。
- 命名問題。即使有犀利的設計師提供了css文件,樣式類的命名也難以符合前端開發規範和需求(真有這樣的設計師歡迎私信推薦給我(●^◡^●))
所以這種處理方式不推薦也不在我們的討論範圍之列。
自動化工具
當我們擁有了自動化工具的時候,部分問題就可以對整個流程進行優化了。
根據psd切出小圖標(前端必備,自己動手,豐衣足食),並把小圖標放入源文件夾。
構建工具自動生成圖片和css文件,並根據小圖標名生成對應的樣式名。
代碼中引入樣式和圖片。
配置文件
以 npm 的 gulp.spritesmith 模塊爲例實現整個流程。
這是 gulpfile.js 中配置的任務:
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
gulp.task('png', function () {
gulp.src('./src/*.png')
.pipe($.spritesmith({
imgName: 'icon.png', //參數,生成圖片文件名
cssName: 'icon.css', //參數,生成的樣式文件名
cssTemplate: './src/png_template.hbs' //參數,樣式文件模板的路徑,默認使用的是handlerbars模板
}))
.pipe(gulp.dest('dist/png'));
});
功能比較強大,除了css文件外還可以生成scss和less文件,同時也可以用模板文件對其進行格式化。這裏我自定義了一個 png_template.hbs 文件,內容如下:
// 主要增加了一個通用樣式,給圖標賦予內聯塊級樣式
.icon {
display: inline-block;
}
{{#sprites}}
.icon-{{name}} {
background-image: url({{{escaped_image}}});
background-position: {{px.offset_x}} {{px.offset_y}};
width: {{px.width}};
height: {{px.height}};
}
{{/sprites}}
開發流程
配置完成之後,在源文件夾中放入兩個 question.png、hook.png 兩個小圖標進行調試。
gulp 處理後生成了兩個文件:icon.css、icon.png。 打開 icon.css,可以看到根據圖標名生成了兩個樣式類:
.icon {
display: inline-block;
}
.icon-hook {
background-image: url(icon.png);
background-position: -40px 0px;
width: 16px;
height: 16px;
}
.icon-question {
background-image: url(icon.png);
background-position: 0px 0px;
width: 40px;
height: 40px;
}
在代碼中使用起來很簡單
// 引用生成的css文件
<link rel="stylesheet" href="./png/icon.css" charset="utf-8">
...
//直接給標籤添加樣式類
<i class="icon icon-hook"></i>
<i class="icon icon-question"></i>
預覽效果見文末截圖
問題
感謝技術的進步和人民生活水平的提高,這種高效的方式馬上碰到一個“天敵”: 高dpr的視網膜屏幕 。
用響應式判斷dpr的話,前面所有的工作量都要倍增,同時還要加載多餘的樣式。而且隨着屏幕更新換代,dpr增多就要多做一張圖片和樣式,想想都太磨人 -_-||
那麼是否有圖片可以自適應不同dpr的屏幕?css3的曙光給我們指引了新的方向。
font-face
也稱作字體圖標,這種技術簡單來說就是把矢量圖合併生成字體文件,然後在css中引用對應的字體編碼即可渲染成圖片。因爲字體是適應各種屏幕的,所以字體圖標也繼承了這個優點。
手動操作
目前有不少製作字體圖標的網站,比較火的有 icomoon 、 阿里巴巴圖標庫 等。
基本操作都是在線上編輯圖標,然後下載一個壓縮包,包含字體文件和樣式。首先的問題是不同圖標大小需要手動調整 font-size 屬性;其次就是手工操作太頻繁:上傳 - 編輯 - 下載;最後就是依賴網絡環境,沒網絡就沒法編輯圖標。既然如此,我們嘗試使用自動化工具離線生成文件。
自動化工具
依然使用的是github上star數比較多的模塊 gulp-iconfont ,但是要同時生成css還需另一個模塊 gulp-iconfont-css 。
配置文件
配置 gulpfile.js
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
gulp.task('iconfont', function () {
// 先配置樣式,再配置字體文件
return gulp.src(['src/*.svg'])
.pipe($.iconfontCss({
fontName: 'iconfont', //字體名
path: './src/font_template.css', //模板文件路徑
cssClass: 'iconfont' //樣式類名
}))
.pipe($.iconfont({
fontName: 'iconfont', //字體名
formats: ['ttf', 'eot', 'woff', 'woff2', 'svg'] //輸出的字體文件格式
}))
.pipe(gulp.dest('dist/font'));
});
此處省略模板文件~
開發流程
配置完成之後,在源文件夾中放入兩個 question.svg、hook.svg 兩個小圖標進行調試。
gulp 處理後生成了6個文件: _icon.css、iconfont.eot、iconfont.svg、iconfont.ttf、iconfont.woff、iconfont.woff2。 打開 _icon.css,可以看到根據圖標名生成了兩個樣式類:
@font-face {
font-family: "iconfont";
src: url('./iconfont.eot');
src: url('./iconfont.eot?#iefix') format('eot'),
url('./iconfont.woff2') format('woff2'),
url('./iconfont.woff') format('woff'),
url('./iconfont.ttf') format('truetype'),
url('./iconfont.svg#iconfont') format('svg');
}
.iconfont:before {
font-family: "iconfont";
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-style: normal;
font-variant: normal;
font-weight: normal;
/* speak: none; only necessary if not using the private unicode range (firstGlyph option) */
text-decoration: none;
text-transform: none;
}
.iconfont-hook:before {
content: "\E001";
}
.iconfont-question:before {
content: "\E002";
}
在代碼中使用起來也很簡單
// 引用生成的css文件
<link rel="stylesheet" href="./font/_icons.css" charset="utf-8">
...
//直接給標籤添加樣式類
<i class="iconfont iconfont-hook"></i>
<i class="iconfont iconfont-question"></i>
預覽效果見文末截圖
使用問題
和之前的介紹的工具一樣,可以使用模板,也可以生成scss、less、css多種格式文件。蛋疼的問題是: 生成的所有的字體圖標都會取最高的那個圖標的高度。也就是說一些圖標需要重新設置高度! 自動化操作瞬間降級爲半自動化~而且生成的圖片還帶鋸齒(不知道是不是配置問題),所以只能算是失敗的方案。
svg sprite
正當愁眉不展之時,看到一篇文章《 未來必熱:SVG Sprite技術介紹 》
(末尾的結束語將字體圖標和svg sprite做了對比,有興趣的朋友可以看一下)才讓我感覺柳暗花明: 原來還有更強大的svg sprite 。將svg矢量圖標整合成一個svg文件,使用的時候以 symbol 或 use 等標籤的形式展現。
手動操作
考慮這個方案之時就沒打算用手動化,因爲如果需要手動操作還不如使用字體圖標,所以直接考慮自動化工具。
自動化工具
使用的是github上star數僅次於gulp-svgstrore的模塊 gulp-svg-sprite 。支持scss、less、css文件格式輸出。
配置文件
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
gulp.task('svg', function () {
return gulp.src('./src/*.svg')
.pipe($.svgSprite({
mode: {
symbol: {
prefix: `.svg-`,
dimensions: '%s',
sprite: '../icon.svg',
symbol: true,
render: {
css: {
dest: '../icon.css'
}
}
}
}
}))
.pipe(gulp.dest('dist/svg'));
});
開發流程
整個流程同上,配置完成之後,在源文件夾中放入兩個 question.svg、hook.svg 兩個小圖標進行調試。
gulp 處理後生成了2個文件: icon.svg、icon.css。 打開 icon.css,可以看到根據圖標名生成了兩個樣式類:
.svg-hook {
width: 16px;
height: 16px;
}
.svg-question {
width: 40px;
height: 40px;
}
非常簡潔有麼有!!!
使用起來稍稍複雜一點:
//引用樣式文件
<link rel="stylesheet" href="./svg/icon.css" charset="utf-8">
...
<svg class="svg-hook">
<use xlink:href="./svg/icon.svg#hook"></use>
</svg>
<svg class="svg-question">
<use xlink:href="./svg/icon.svg#question"></use>
</svg>
預覽效果見文末截圖
相比字體圖標:
1.據說SVG圖標跟字體圖標相比,還支持漸變,甚至彩色圖標。
2.改變大小直接調整width和height屬性即可,而不是調整font-size那種“曲線救國”的方式。
3.填充顏色也很簡單,設置fill屬性的值即可(前提是svg中不能使用fill,如果svg自帶fill屬性,設置失效)。
使用問題
所有的IE瀏覽器(包括IE11)還不支持獲得外鏈SVG文件某個元件。但是也很好解決,使用第三方js即可—— svg4everybody 。
學習前端的同學注意了!!!
學習過程中遇到什麼問題或者想獲取學習資源的話,歡迎加入前端學習交流羣,羣號碼:328058344