Flutter 上字體的另類玩法:FontFeature

在以前的 《Flutter 上默認的文本和字體知識點》《帶你深入理解 Flutter 中的字體“冷”知識》 中,已經介紹了很多 Flutter 上關于字體有趣的知識點,而本篇講繼續介紹 Flutter 上關于 Text 的一個屬性:FontFeature , 事實上相較于 Flutter ,本篇內容可能和前端或者設計關系更密切。

相信本篇絕對是你能看到關于 Flutter FontFeature 相關的少數資料之一。

什么是 FontFeature? 簡單來說就是影響字體形狀的一個屬性 ,在前端的對應領域里應該是 font-feature-settings,它有別于 FontFamily ,是用于指定字體內字的形狀的一個參數。

如下圖所示是 frac 分數和 tnum 表格數字的對比渲染效果,這種效果可以在不增加字體庫時實現特殊的渲染,另外 Feature 也有特征的意思,所以也可以理解為字體特征。

image

我們知道 Flutter 默認在 Android 上使用的是 Roboto 字體,而在 iOS 上使用的是 SF 字體,但是其實 Roboto 字體也是分很多類型的,比如你去查閱手機的 system/fonts 目錄,就會發現很多帶有 Roboto 字樣的字體庫存在。

image

所以 Roboto 之類的字體庫是一個很大的字體集,不同的 font-weight 其實對應著不同的 ttf ,例如默認情況下的 Roboto 是不支持 font-weight 為 600 的配置

image

所以如下圖所示,如果我們設置了 w400 - w700weight ,可以很明顯看到中間的 500 和 600 其實是一樣的粗細,所以在設置 weight 或者設計 UI 時,就需要考慮不同平臺上的 weight 是否支持想要的效果。

image

回歸到 FontFeature 上,那 Roboto 自己默認支持多少種 features 呢? 答案是 26 種,它們的編碼如下所示,運行后效果也如下圖所示,從日常使用上看,這 26 種 Feature 基本滿足開發的大部分需求。

"c2sc"、 "ccmp"、 "dlig"、 "dnom"、 "frac"、 "liga"、 "lnum"、 "locl"、 "numr"、 "onum"、 "pnum"、 "salt"、 "smcp"、 "ss01"、 "ss02"、 "ss03"、 "ss04"、 "ss05"、 "ss06"、 "ss07"、 "tnum"、 "unic"、 "cpsp"、 "kern"、 "mark"、 "mkmk"

image

而 iOS 上的 SF pro 默認支持 39 種 Features , 它們的編碼如下所示,運行后效果也如下圖所示,可以看到 SF pro 支持的 Features 更多。

"c2sc"、 "calt"、 "case"、 "ccmp"、 "cv01"、 "cv02"、 "cv03"、 "cv04"、 "cv05"、 "cv06"、 "cv07"、 "cv08"、 "cv09"、 "cv10"、 "dnom"、 "frac"、 "liga"、 "locl"、 "numr"、 "pnum"、 "smcp"、 "ss01"、 "ss02"、 "ss03"、 "ss05"、 "ss06"、 "ss07"、 "ss08"、 "ss09"、 "ss12"、 "ss13"、 "ss14"、 "ss15"、 "ss16"、 "ss17"、 "subs"、 "sups"、 "tnum"、 "kern"

image

所以可以看到,并不是所有字體支持的 Features 都是一樣的,比如 iOS 上支持 sups 上標顯示和 subs 下標顯示,但是 Android 上的 Roboto 并不支持,甚至很多第三方字體其實并不支持 Features 。

同樣在 Web 上也存在各種限制,比如 swsh(花體)默認下基本不支持瀏覽器,fwid 、 nlck 不支持 Safari 瀏覽器等。

有趣的是,在 Flutter Web 有一個渲染文本時會變模糊的問題#58159,這個問題目前官方還沒有修復,但是你可以通過給 Text 設置任意 FontFeatures 來解決這個問題。

因為出現模糊的情況一般都是因為使用了 canvas 標簽繪制文本,而如果 Text 控件具有 fontFeatures 時,就會被設置為 <p> + <span> 進行渲染,從而避免問題。

最后,如果對 FontFeature 還感興趣的朋友,可以通過一下資料深入了解,如果你還有什么關于字體上的問題,歡迎留言討論。

補充內容

基于網友的問題再補充一下拓展知識,畢竟這方面內容也不多

事實上在 dart 里就可以看到對應 FontWeight 約定俗稱用的是字體集里的什么字體:

名稱
Thin w100
Extra w200
Light w300
Normal/regular/plain w400(默認)
Medium w500
Semi-bold w600
Bold w700
Extra-bold- w800
Black 900

所以如果對于默認字體有疑問,可以在你的手機字體找找是否有對應的字體,比如雖然我們說 roboto 沒有 600 ,但是如果是 roboto mono 字體集是有 600 的 fontweight,甚至還有 600 斜體: https://fonts.google.com/specimen/Roboto+Mono 。

另外注意這是 Flutter 而不是原生,具體實現調用是在 Engine 的 paragraph_skia.ccparagraph_builder_skia.cc 下對應的 setFontFamilies 相關邏輯,當然默認字體庫指定在 typography.dart 下就看到,例如 'Roboto' 、 '.SF UI Display''.SF UI Text' 、'.AppleSystemUIFont''Segoe UI'

名稱
Android,Fuchsia,Linux Roboto
iOS .SF UI Display,.SF UI Text
MacOS .AppleSystemUIFont
Windows Segoe UI

例如:.SF Text 適用于更小的字體;.SF Display 則適用于偏大的字體,我記得分水嶺好像是 20pt 左右,不過 SF(San Francisco) 屬于動態字體,系統會動態匹配。

另外如果你在 Mac 的 Web 上使用 Flutter Web,可以看到指定的是 .AppleSystemUIFont ,而對于 .AppleSystemUIFont 它其實不算是一種字體,而是蘋果上字體的一種集合別稱:

[圖片上傳失敗...(image-40f5ce-1648368234737)]

還有,如果你去看 Flutter 默認自帶的 cupertino/context_menu_action.dart ,就可以看到一個有趣的情況:

為了強調和 iOS 上的樣式盡量一直,當開發者配置 isDefaultAction == true 時,會強行指定 '.SF UI Text' 并指定為 FontWeight.w600。

當然,前面我們說了那么多,主要是針對英文的情況下,而在中文下還是有差異的,之前的文章也介紹過:

  • 默認在 iOS 上:

    • 中文字體:PingFang SC
    • 英文字體:.SF UI Text.SF UI Display
  • 默認在 Android 上:

    • 中文字體:Source Han Sans / Noto
    • 英文字體:Roboto

例如,在蘋果上的簡體中文其實會是 PingFang SC 字體,對應還有PingFang TCPingFang HK 的繁體集,而關于這個問題在 Flutter 上之前還出現過比較有意思的 bug :

用戶在輸入拼音時,iOS 會在中文拼音之間添加額外的 unicode \u2006 字符,比如輸入 "nihao" ,iOS 系統會在 skia 中添加文字 “ni\u2006hao ”,從而導致字體無效的情況。

當然后續的 #16709 修復了這個問題 ,而在以前的文章我也講過,當時我遇到了 “Flutter 在 iOS 系統上,系統語言是韓文時,在和中文一起出現會導致字體顯示異常" 的問題

image.png

解決方法也很簡單,就是給 fontFamilyFallback 配置上 ["PingFang SC" , "Heiti SC"] 就可以了,這是因為韓文在蘋果手機上使用的應該是 Apple SD Gothic Neo 這樣的超集字體庫,【廣】這個字符在這個字體集上是不存在的,所以就變成了中文的【廣】;

image.png

所以可以看到,字體相關是一個平時很少會深入接觸的東西,但是一旦涉及多語言和繪制,就很容易碰到問題的領域

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,197評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,415評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,104評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,884評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,647評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,130評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,208評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,366評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,887評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,737評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,939評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,478評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,174評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,586評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,827評論 1 283
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,608評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,914評論 2 372

推薦閱讀更多精彩內容