Technology︰為中文字體檔瘦身
前言
在開發網頁的過程中,尤其是希望用到特別的中文字體時,由於中文字體檔案動輒有數十 MB 大小,下載需要一點時間。因此通常都會以圖片代替文字。用圖片代替文字的短處是無法把文字拷貝、只有單一尺寸、修改起來麻煩…等。究竟有沒有其他方法?
準備
如果能把用不著的文字從字體檔中刪除,檔案體積將會縮小,變成適合在網頁中加載。在 Node.js 中有一個名為「fontmin」的模組可以滿足到這個需求。在 Terminal 輸入:
npm install fontmin gulp-rename fs
它會安裝程式所需要的模組。
程式
//---------------------------------------------------------------------------------------- // Font File Minifier //---------------------------------------------------------------------------------------- // Written by : Alvin LAU // Copyright Fimmick Limited, 2019. All rights reserved. //---------------------------------------------------------------------------------------- // Require modules var _GULPRENAME = require("gulp-rename"); var _FONTMIN = require("fontmin"); var _FS = require("fs"); //---------------------------------------------------------------------------------------- // Global variables var _now = new Date(); var year = _now.getFullYear().toString(); var month = _now.getMonth().toString(); var date = _now.getDate().toString(); var hours = _now.getHours().toString(); var minutes = _now.getMinutes().toString(); var seconds = _now.getSeconds().toString(); month = (month.length === 2) ? month : "0"+month; date = (date.length === 2) ? date : "0"+date; hours = (hours.length === 2) ? hours : "0"+hours; minutes = (minutes.length === 2) ? minutes : "0"+minutes; seconds = (seconds.length === 2) ? seconds : "0"+seconds; //======================================================================================== // Program start console.log("\n##----------------------------------------------------------"); console.log("## Font File Minifier"); console.log("## Written by Alvin LAU"); console.log("## Copyright Fimmick Limited, 2019. All rights reserved."); console.log("##----------------------------------------------------------\n"); //---------------------------------------------------------------------------------------- // Reading parameters var argu = process.argv.slice(2); var inputFontFilename = "NotoSansTC-Medium.ttf"; var arguGlyphs = ""; for (var i=0; i<argu.length; i++) { switch (argu[i]) { case "-f": case "--font": { inputFontFilename = argu[i+1]; } break; case "-g": case "--glyphs": { arguGlyphs = argu[i+1]; } break; } } if (arguGlyphs == "") { // No glyphs provided, show instruction console.log("Usage:"); console.log(" node fontminifier.js -g <characters> -f <fontfile>\n"); console.log("Options:"); console.log(" --glyphs"); console.log(" -g = Characters that you want to keep in font file.\n"); console.log(" --font"); console.log(" -f = Font source filename in TTF format with extension\n"); console.log("Example:"); console.log(" node fontminifier.js -g 0123456789 -f Arial.ttf\n"); process.exit(1); } //---------------------------------------------------------------------------------------- // Main process console.log("Input font file: "+inputFontFilename); console.log("Glyphs to be keep: "+arguGlyphs); // Font file name var fontFilename = inputFontFilename.split("."); var outputFilename = fontFilename[0]+"_"+year+month+date+hours+minutes+seconds+".ttf"; // Set the files to be optimized var fontPath = "./"+inputFontFilename; // Set the destination folder to where your files will be written var outputPath = "./"; // Check if font file is exists. if (_FS.existsSync(fontPath) == false) { // If do not exists then will stop the process console.error("### Font file not found...\n"); process.exit(1); } // Set up by fontmin var fontmin = new _FONTMIN() .use(_GULPRENAME(outputFilename)) .src(fontPath) .dest(outputPath); if (arguGlyphs != "") { console.log("\nProcessing..."); fontmin.use(_FONTMIN.glyph({ text: arguGlyphs, hinting: false })); } // Start minifying font with the given settings. fontmin.run(function(err, files) { if (err) { console.error("### Something went wrong...\n"); throw err; } console.log("Minify done: "+outputPath+outputFilename+"\n"); process.exit(0); });
解說
讓我們來了解程式的運作。
// Require modules var _GULPRENAME = require("gulp-rename"); var _FONTMIN = require("fontmin"); var _FS = require("fs");
程式最開端是載入三個需要的模組。「gulp-rename」是用於更改檔案名稱;「fontmin」是字體瘦身的核心;「fs」主
要是檔案相關的處理。
// Global variables var _now = new Date(); var year = _now.getFullYear().toString(); var month = _now.getMonth().toString(); var date = _now.getDate().toString(); var hours = _now.getHours().toString(); var minutes = _now.getMinutes().toString(); var seconds = _now.getSeconds().toString(); month = (month.length === 2) ? month : "0"+month; date = (date.length === 2) ? date : "0"+date; hours = (hours.length === 2) ? hours : "0"+hours; minutes = (minutes.length === 2) ? minutes : "0"+minutes; seconds = (seconds.length === 2) ? seconds : "0"+seconds;
向系統取得當刻的時間,並把數值分別設定在對應的變量中。
var argu = process.argv.slice(2); var inputFontFilename = "NotoSansTC-Medium.ttf"; var arguGlyphs = ""; for (var i=0; i<argu.length; i++) { switch (argu[i]) { case "-f": case "--font": { inputFontFilename = argu[i+1]; } break; case "-g": case "--glyphs": { arguGlyphs = argu[i+1]; } break; } } if (arguGlyphs == "") { // No glyphs provided, show instruction console.log("Usage:"); console.log(" node fontminifier.js -g <characters> -f <fontfile>\n"); console.log("Options:"); console.log(" --glyphs"); console.log(" -g = Characters that you want to keep in font file.\n"); console.log(" --font"); console.log(" -f = Font source filename in TTF format with extension\n"); console.log("Example:"); console.log(" node fontminifier.js -g 0123456789 -f Arial.ttf\n"); process.exit(1); }
這段是讀取參數,如果是「-f」或「–font」就把數值儲存在「inputFontFilename」;如果是「-g」或「–glyphs」就把數值儲存在「arguGlyphs」。當沒有指定字體檔名時,會使用預設的「NotoSansTC-Medium.ttf」字體檔案。
由於這是一個瘦身程式,如果沒有指定保留哪些字元時,運作便會變得沒有意義,因此程式會停止執行。也有可能是用戶不清楚使用方法,所以同時會顯示使用說明。
// Main process console.log("Input font file: "+inputFontFilename); console.log("Glyphs to be keep: "+arguGlyphs); // Font file name var fontFilename = inputFontFilename.split("."); var outputFilename = fontFilename[0]+"_"+year+month+date+hours+minutes+seconds+".ttf"; // Set the files to be optimized var fontPath = "./"+inputFontFilename; // Set the destination folder to where your files will be written var outputPath = "./"; // Check if font file is exists. if (_FS.existsSync(fontPath) == false) { // If do not exists then will stop the process console.error("### Font file not found...\n"); process.exit(1); }
接下來是依照參數數值去準備好輸入路徑、輸出路徑、路徑檔名。同時也會檢查指定的字體檔案是否存在。沒有字體檔案會甚麼也做不來,這時就需要顯示錯誤訊息。
// Set up by fontmin var fontmin = new _FONTMIN() .use(_GULPRENAME(outputFilename)) .src(fontPath) .dest(outputPath); if (arguGlyphs != "") { console.log("\nProcessing..."); fontmin.use(_FONTMIN.glyph({ text: arguGlyphs, hinting: false })); }
一切就緒,現在要建立核心模組,並把準備好的數值通知模組。
// Start minifying font with the given settings. fontmin.run(function(err, files) { if (err) { console.error("### Something went wrong...\n"); throw err; } console.log("Minify done: "+outputPath+outputFilename+"\n"); process.exit(0); });
最後就是執行瘦身動作。如果當中出現錯誤時,就顯示錯誤訊息。成功的話則顯示輸出檔名。要執行程式,在「Terminal」輸入:
node fontminifier.js -g 0123456789 -f phosphate.ttf
「-g」參數後面的是要保留的文字。「-f」參數後面的是輸入的字體檔案名稱;程式會在檔案名稱後加入當刻時間,作為
輸出的字體檔案名稱。留意:程式只支援 TTF 格式,TTC, OTF,…等是不支持。這段指令的意思是讀取
「phosphate.ttf」字體檔,只保留「0123456789」字符,其他的都刪除掉。完成後會有一個類似
「phosphate_YYYYMMDDHHIISS.ttf」的檔案出現;它就是瘦身後的字體檔案。
希望以上的內容對你有幫助。如果你對我們的服務感興趣,歡迎與我們聯絡!大家亦可留意我們的 Facebook 和 Instagram 以獲得更多關於營銷及開發方面的資訊。