如何實現 Medium for iOS 那般的下劃線效果?

(圖片來自: jason2be)

注意其中 g 的下劃線樣式. 也許是見識過於淺薄的緣故, 以前從來沒有見過這樣的下劃線實現, 感覺非常美觀, 不知道這種效果是通過何種方式實現的?

有朋友給出了 Medium 設計師的文章: Crafting link underlines on Medium. 但是實際上網頁版下劃線和 iOS 版的略有不同:

(圖片來自文章)

而文章中提到的最接近 iOS 版本的實現方式又被否決了:

(圖片來自文章)


撰文的 Medium 設計師是做前端設計而非 iOS 客戶端設計的,換言之 iOS 方面的設計跟他沒什麼關係……

他遇到的問題是,Chrome 聲明 text-decoration:
underline 畫出來的下劃線太粗了。所以比起避讓字母的 descender(降部),粗細顯然是更重要的問題。後來他們的方案是使用 CSS
漸變重繪下劃線解決粗細問題,效果有目共睹。

至於避讓降部,他們雖然沒有什麼特別理想的方法(Medium for iOS 的方案恐怕是數值計算,估計前端也用不了),不過原文下有人貼出了自己的方案:JavaScript don』t underline g/j/q/p/y,思路是對於含有降部的字母取消下劃線。

這個方法如果仔細調教的話,在前端方面倒也能做到接近 Medium for iOS 客戶端的效果。我就寫了一個。

Edit fiddle - JSFiddle

(span 中的那個 p 會礙事,所以得挑一個名稱沒有降部的 HTML 標籤 orz)

對比 4s 中 iOS 客戶端的效果:

具體的方案是,對 g 完全取消下劃線,對 jpqy 用多重 text-shadow 掩蓋下劃線。這樣做有一個缺點是 y 的降部是斜的,那麼靠渲染出來的文字陰影來掩蓋的話,下劃線的切口也是斜的。

另一個更重要的問題是,這個方案對字母 g 可以保證效果,但對 jpqj 依然是使用 text-shadow 掩蓋下劃線,並沒有解決不同背景色的問題,而且雖然減少了渲染文字陰影的成本但也增加了選擇器的成本。所以這並不是最終方案。

不過說起來,越來越多的字體會有多個字重與 italic 的設計,那麼添加一組下劃線的版本照說也是合理的。


這才叫設計:看Medium如何精雕細琢下劃線


找個時間來嘗試一下 Android 上的實現。沒細思考,腦子裡的第一想法如下:

1. 使用 Canvas 來繪製下劃線

2. 取得字體的 Path

3. 判斷下劃線和字體 Path 是否相交,尋找交點

4. 判斷交點之間的下劃線是否要繪製

忙裡偷閒,簡單實現了一下,還不具備實用價值,只是驗證方案,效果如下圖:

思路基本不變,但要做到可用控制項還要再調整一下。

佔個坑,代碼整理之後再更新細節實現。===============================

貌似老闆又在瞄我在做什麼 @.@ ,要趕緊去解 Bug 先


coretext.framework


最近發現的另一個工具 https://eager.io/showcase/SmartUnderline/

可仿Medium的下劃線


由於沒使用過這個APP,也不做iOS,我只能猜測一下實現方法。

如果在Android上做,我應該會採用分層的方法,字和線是兩個層,這樣應該可以實現上面的效果。

iOS應該同理。

剛剛回答完就意識到了我的愚蠢……如果按照我的辦法,那麼g處的下劃線應該在g下方的空白也有顯示,但是圖裡的完全沒有,那麼我提供的思路應該是錯的……


已經驗證的一種實現方法是:

複寫onDraw方法,繪製三次,

第一次繪製普通情況下帶下劃線的問題;

第二次設置Paint style 為Paint.Style.STROKE,對字體進行加粗處理,並設置一定Stoke Width;

前兩次繪製結果使用PorterDuff.Mode.DST_OUT,取第一次未相交部分;

經過前兩次其實基本可以獲得斷線效果,但好像粗體對於Stroke字體有一些內部斷裂效果,為修復這些斷裂,進行第三次繪製,在這次僅繪製不帶下劃線的普通字體。

Done

另一種思路是自己手動檢測並繪製下劃線,不知道在iOS上的是使用何種方式實現這一效果。


推薦閱讀:

一個android工程師除了需要編寫代碼的技能,還需要什麼?
Android Studio項目應該提交哪些文件到GitHub上?
Android Studio有哪些非常好用的插件?
有什麼好用的Android Studio的插件值得推薦?
如何做好安卓應用的界面設計?

TAG:網頁設計 | 前端開發 | iOS開發 | Android開發 | 字體排印 |