字體嵌入是 Flash 應用開發的永恆痛點:嵌入全字符導致體積暴漲,嵌入部分字符又需反覆修改發布。本文提出一套「字體庫 SWF + 運行時加載 + CSS 樣式表」的最佳實踐方案,實現字體文件與業務代碼解耦、字符集熱更新、多項目複用。
| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| IDE 文本框勾選嵌入 | 最簡單、所見即所得 | 字符集修改需重新打開 FLA、無法運行時動態增減 | 靜態頁面、字符集固定的小專案 |
| Flex CSS @font-face + mxmlc 編譯 SWF | 運行時加載、分離字體文件 | unicodeRange 編寫繁瑣、難以可視化管理字符集 | Flex 應用、模組化架構 |
| AS3 [Embed] 元數據標簽 | 編譯期嵌入、類型安全 | 字符集寫死在代碼、修改需重新編譯 | 純 AS3 專案、字符集固定 |
| 字體庫 SWF + 運行時加載(本文推薦) | 可視化編輯字符集、運行時熱加載、CSS 樣式分離、多項目複用 | 需維護字體庫 FLA、初次搭建稍繁瑣 | 中大型專案、多語言、字符集頻繁變更、團隊協作 |
project/ ├── font_lib.fla → 編譯 → font_lib.swf (字體庫:舞台放文本框,手動勾選嵌入字符) ├── font_loader.as → 編譯 → font_loader.swf (加載器:Embed font_lib.swf + Font.registerFont) ├── style.css (樣式表:定義 font-family、font-size 等) └── main_app.swf (主應用:運行時加載 font_loader.swf + style.css)
font_lib.swf。
package {
import flash.display.Sprite;
import flash.text.Font;
import flash.events.Event;
[Embed(source="font_lib.swf", fontName="MyCustomFont")] // fontName 必須與 font_lib.fla 中文本框使用的字體名一致
private var FontLibClass:Class;
public class FontLoader extends Sprite {
public function FontLoader() {
Font.registerFont(FontLibClass);
dispatchEvent(new Event(Event.COMPLETE)); // 通知主應用字體就緒
}
}
}
編譯為 font_loader.swf(可用 Flash Builder、mxmlc 或 Flash Professional 建立 Document Class 編譯)。
.headline {
font-family: 'MyCustomFont'; /* 必須與 fontName 完全一致 */
font-size: 24;
color: #333333;
}
.body {
font-family: 'MyCustomFont';
font-size: 16;
leading: 4;
}
var styleSheet:StyleSheet = new StyleSheet();
var fontLoader:Loader = new Loader();
var cssLoader:URLLoader = new URLLoader();
fontLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onFontLoaded);
cssLoader.addEventListener(Event.COMPLETE, onCssLoaded);
cssLoader.load(new URLRequest("style.css"));
function onCssLoaded(e:Event):void {
styleSheet.parseCSS(e.target.data);
}
function onFontLoaded(e:Event):void {
// 字體已註冊,現在可以使用
var tf:TextField = new TextField();
tf.embedFonts = true; // 關鍵:啟用嵌入字體渲染
tf.styleSheet = styleSheet;
tf.htmlText = "這是動態加載的標題 正文內容...";
addChild(tf);
}
fontLoader.load(new URLRequest("font_loader.swf"));
font_lib.fla,在文本框 Embed 面板勾選/輸入字符,無需懂代碼。font_lib.swf 覆蓋線上文件,主應用無需重新編譯,用戶刷新即可生效。font_lib_cn.fla、font_lib_en.fla、font_lib_jp.fla,運行時按語言加載對應 SWF。style.css 調整字號、顏色、行距。StyleSheet.parseCSS() 運行時動態切換主題(換膚)。同一 font_lib.swf + font_loader.swf 可供多個專案共用,統一品牌字體,減小總體積。
font_lib_base.swf(ASCII+常用標點)、font_lib_cn1.swf、font_lib_cn2.swf…FontLoader 類,fontName 可相同(同族字體)或不同(如 Heiti-Base, Heiti-Ext1)。對於長文本輸入場景,嵌入字體渲染性能較差,可檢測運行環境:
if (Capabilities.cpuArchitecture == "ARM" && text.length > 200) {
// 移動端長文本改用 StageText 原生輸入
useStageTextInput();
} else {
// 短文本/桌面端使用嵌入字體 TextField
useEmbeddedFontTextField();
}
無法運行時動態定義嵌入字符是 Flash Player/AIR 的底層限制(字體輪廓在編譯時燒錄進 SWF)。若極度需要運行時動態字符集,唯一出路是:
fontas、typeface.js 移植版),解析 TTF/OTF 文件實時光柵化,但性能開銷大。Font.enumerateFonts() 獲取設備字體),僅在品牌字體必要時嵌入。「字體庫 SWF + 運行時加載器 + CSS 樣式表」三件套,是目前 Flash/AIR 生態下工程化程度最高、維護成本最低的字體嵌入方案。它將「字符集管理」歸還給可視化工具,將「樣式管理」歸還給 CSS,將「加載邏輯」封裝在獨立加載器中,實現關注點分離。對於中大型專案、多語言產品、需頻繁調整字符集的團隊,強烈建議採用此架構。