天天看點

H5頁面快速搭建之進階字型應用實踐

最近在開發一個 h5 活動頁快速搭建平台,可以通過拖拽編輯圖檔,文字等元素元件,快速搭建出一個移動端的活動頁面,基本互動和成品效果類似 ppt 軟體。這類活動大量在微信等平台上傳播,其中會包含各種動畫和特效,而各類進階藝術字型(如:方正蘭亭黑,方正彩雲,方正大草,方正劍體等)的應用也非常廣泛。

之前使用者隻能通過 ps 等軟體将文字轉化為圖檔再貼到平台上使用。使用成本很高,修改,調試都非常不便,而且圖檔占用的資源也比較多,為了降低使用者的使用成本,基于一站式搭建的理念,我們需要将進階字型的使用透明化,使使用者和使用 ppt 一樣直接選擇字型使用即可。

第一種方案是通過使用者輸入的文字,和選擇的字型,通過伺服器生成對應的圖檔來使用。這種方案的優點是邏輯簡單,缺點是搭建/修改時增加了複雜度,調試時無法實時預覽文字在活動中的效果。而且容易出現大量備援圖檔,最終頁面的圖檔請求也會增加。

第二種方案是調用 iconfont.cn 的服務接口,通過傳遞字型和文字内容來擷取字型檔案。這種方案的優點是可以直接利用現有成熟平台,開發成本低,可靠。缺點是增加了外部依賴,不但面臨合作方配合的限制,而且無法自行控制可供的選擇字型等。

最終采用的的第三種方案是直接使用 iconfont.cn 的 node.js 子產品 (font-carrier) ,自行解析/生成字型,将生成的字型放在我們自己申請的 oss 中存儲使用。這種方法的開發量最大,且要消耗額外的 oss 資源,但是整個流程獨立自主,可以不斷定制優化,自行添加字型等,由于我們的服務隻面向移動端,是以隻需要生成 ttf 或者 woff 一種檔案類型即可相容。

以 ttf 檔案為例,字型檔案中主要包含了字型頭表,位置索引表和圖中繼資料表等等,其中最核心的部分就是圖中繼資料表,也就是字形描述表,它可以包含可變數目的圖元,每個圖元可以有不同數目的控制點,甚至還可以有數量可變的圖元指令,通過位置索引表對應到每個字元上,通過圖中繼資料表,使其隻包含需要使用的字元的圖元描述。即可最小化字型,使其可用于生産環境的頁面中,其他類型的字型檔案(如 woff, eot, svg 等)原理也是大同小異,僅僅是壓縮方式和字形描述規範不同,也可以互相轉化。

font-carrier 子產品使用 opentype 子產品分析 ttf 檔案,可以檔案的内容腳本化,使其成為一個字元 unicode 編碼和其字形描述的鍵值對象。通過對這個對象的 min 方法,可以使其最小化,并且再逆向生成檔案 buffer 供使用者使用。

在程式啟動後通過 font-carrier 子產品将本地的字型檔案包裝成字型對象,儲存在伺服器記憶體中。

使用者儲存頁面時,記錄下此活動所有使用的進階字型和相應的文字内容

通過 font-carrier 子產品找到字型對應的字型對象,使用 min 指令生成最小化的字型對象

使用 min 指令生成縮小後的字型檔案,儲存到 oss,并以活動的 id 為路徑,字型的名字為檔案名。

最終渲染時通過記錄的活動使用的字型名拼出 oss 路徑來引用檔案

由于字型數量較多,啟動時将本地字型檔案包裝成字型對象的時間非常長,可達到數十分鐘。

字型對象常駐記憶體,占用巨大,甚至可能直接吃光記憶體

因為 font-carrier 子產品生成的字型對象無法通過檔案來持久化儲存,隻能生成後常駐記憶體中,而字型的數量多,大小也大,是以不管是生成的時間,生成時消耗的性能,生成後占用的記憶體都非常巨大。是以問題的關鍵在于如何把字型的分析結果持久化儲存在伺服器中。

在咨詢了 font-carrier 子產品的開發者後,了解到 font-carrier 子產品還有生成字型的 svg 片段的方法,可以将字型的圖中繼資料轉變為 svg 輸出,并可以将 svg 逆向導入到空字型檔案中來生成最終字型檔案。

通過将字型分析轉譯後的 svg 片段結果儲存在資料庫中,即可持久化分析結果。使用的時候通過建立空字型->配置字元-svg 的對應關系->提取字型->上傳到 oss 的流程來使用最小化後的字型即可。

建立提取字型任務,運作時周遊字型檔案,提取其中的 svg 片段存入資料庫

以下是一段方正喵嗚體中的“我”字提取的 svg 片段

儲存活動時建立空字型,導入需要的字元和其對應的 svg,并将這個字型儲存到 oss

最終渲染時通過的記錄的活動使用的字型名拼出 oss 路徑來引用檔案

在正常運作了一段時間後,使用者回報了新的問題,編輯和預覽時的字寬度不比對,現象為所有的字元都變為了全角模式,數字,字母和符号,都占用了一個漢字的位置。如圖:

H5頁面快速搭建之進階字型應用實踐

經過排查和測試,最後發現原因在于生成 svg 片段時,子產品給這個 svg 加上了寬和高,這是不必要的,在顯示漢字等全角字元時,一切正常,而在顯示半角字元時,則會導緻兩邊出現空隙。

在無法改變 font-carrier 子產品的前提下,隻能在我們自己的流程中加更新檔,我在讀取 svg 使用前,額外增加了替換代碼将寬高删除,證明可以解決該問題。另外我也知會了子產品開發者,在未來的版本中修複此問題。修複後效果如圖:

H5頁面快速搭建之進階字型應用實踐

目前我們采用引用字型檔案的方式來定義進階字型,而最近團隊的無線端最佳實踐的要求,無線端使用的字型将字型檔案 base 64 化,以減少請求數,未來我們也将改造成這種方式,不但符合最佳實踐的要求,同時還可以節省 oss 存儲的資源。

下一階段我們将調研 svg 在移動端的相容性和性能,未來開發的插入幾何形狀功能将考慮使用這一技術,同是我們也會嘗試直接用 svg 繪制字型,産生更多的可能性(比如 svg 動畫等),需要考慮相容性和漸進方案。

轉載自:http://taobaofed.org/blog/2016/04/12/webfont-practice/

作者:龍馭