您當前的位置:首頁 > 攝影

藝術字!實現可複用控制檯的列印功能

作者:由 AI程式設計自習室 發表于 攝影時間:2020-11-24

之前在使用一些開源專案時,經常會看到在控制檯輸出專案大大的 LOGO。例如:

hexo minos 主題啟動時在控制檯裡會顯示「MINOS」文案

fis3 啟動時也會有顯示「FIS」

新增這種大號「藝術字」可以達到「品牌露出」的效果,當然,也是程式設計師特有「情趣」的體現。

但它們的實現方式無外乎把編排好的 Logo 透過

console。log

輸出。這種方式問題在於它幾乎沒有任何複用能力,而且一些需要轉義的情況還會導致字串的可維護性極差。因此,我花了一個週末的時候,實現了一個易用的、可複用的控制檯「藝術字」lib。這樣,下次有新的需求,只需要把正常的文字傳給它,它就可以幫你

自動編排與列印

藝術字!實現可複用控制檯的列印功能

1。 目標

正如上節所說,目前一般專案的做法都是自定寫一串特定的文字,例如 minos:

藝術字!實現可複用控制檯的列印功能

還有 fis3 這種由於需要新增轉義所以顯得凌亂不好維護的

藝術字!實現可複用控制檯的列印功能

這種些方式都是透過「硬編碼」來實現的,如果有了新專案或需求變動還得重新編排調整。

因此,準備實現一種能夠根據輸入的字串進行自動排版展示的控制檯「藝術字」列印庫,例如透過

yo(‘yoo-hoo’)

就會輸出:

藝術字!實現可複用控制檯的列印功能

下次如果文案改了,直接換下字串引數就行 ——

yo(‘new-one’)

藝術字!實現可複用控制檯的列印功能

總結來說,就是實現一個通用的、可複用的控制檯「藝術字」列印功能。基於這個目標開發了 yoo-hoo這個庫。

下面來說說大致怎麼實現。

2。 如何實現

和其他字型顯示的需求類似,我們可以將功能抽象為三個部分:

字型庫的生成

字型的排版

字型的渲染

這裡我們先說一下字型的渲染。

2。1。 字型渲染

之所以先說這部分,是因為它會影響排版資訊的輸出格式。

其實字型渲染這部分並沒有什麼特別的,我們在控制檯這個環境,受限於 API,基本就是使用

console。log

來將內容「渲染」到螢幕上。不過,正是這裡的「渲染」形式的限制,會倒推我們的排版方式。

我們知道,控制檯基本都是單行順序渲染的,大致就是「Z」字型。同時,由於我們的「藝術字」會佔據多行,所以最終的渲染不是按單個字順序渲染的,需要先排好版,然後按行來逐步渲染到螢幕上。

這有點像是咱們常見的印表機。如果你要列印一個蘋果,它會從上往下逐步打印出這個蘋果,而不是直接像蓋章那樣直接印刷一個蘋果。

下面我們會先介紹字型庫的生成,而不是緊接挨著的字型排版。因為排版是一個承上啟下的過程,當我們確定了上下游環節,這塊的邏輯自然也就確定了。

2。2。 字型庫生成

當我們想要實現可複用能力時,因此我們需要找到或者抽象出系統內邏輯上的最小可複用單元 —— 在這裡顯然就是字元。簡單來說,對於輸入字串

JS

時,如果我們能找到對應的 J 和 S 的字元表示形式,輔以排版,理論上就有能力實現我們的目標。這有點像是咱們老祖宗的活字印刷術。

所以在字型庫這裡,我們會有一個字義與字型的對映。這個其實和咱們前端常見的字型檔案內格式的思想一樣,都需要有這麼一個對映關係。

字型哪裡來呢?好吧,我也是用了一個笨辦法 —— 自己「手繪」 。舉個例子,下面就是我「手繪」的 1:

藝術字!實現可複用控制檯的列印功能

繪製的過程是枯燥的,好再很多字型的區域性是有一定複用的,簡化了這項繁瑣的工作。當然,這只是一次性的工作,一旦建立好一類「字型」,以後就不需要再重複這項工作了。

我把上面這個內容存在一個單獨的檔案中,目前直接以 。txt 為字尾,這就是我們的字型原始格式。之所以不放在 。js 中,是因為 JavaScript 中

\

是想要轉義的,這樣文字的視覺和最後的呈現效果就不一致了,不利於除錯和維護。

原始字型檔案分為兩部分:

上面第一行是字義,支援一個多個字義對應一個圖形。例如

·

*

我使用了同一個圖形。多個字義間空格分割,不換行。

除去第一行,剩下的內容就是字型。

理論上,我們可以以這個原始字型檔案來作為字型庫了,透過 NodeJS 中的

fs

模組讀取並解析檔案內容即可得到對映關係。

但我希望它也能在非 NodeJS 環境(例如瀏覽器)中使用,所以不能依賴

fs

模組。這裡做了一個原始檔案的解析指令碼,生成對應的 JS 模組。由於我們並不直接維護這些生成的 JS 模組,所以它的可讀性不重要,可以設計資料格式的時候可以完全面向後續的排版流程。

首先實現一個簡單的解析器來解析第一行的字義。這也類似一個詞法解析器,但由於語法規則極其弱智(簡單),所以也就不用多說了,大致如下:

藝術字!實現可複用控制檯的列印功能

下面就是處理字型部分。之所以需要處理字型,是因為上面提到的轉義問題。由於我們在原始格式中使用了

\

來進行字型展示,而將其直接放入生成的 JS 檔案中這個

\

就變為了轉義符,要想正常展示需要變為

\\

。一種方式是正則匹配,將所有源文字中的

\

替換為

\\

再寫入。但我選擇了另一種方式。

將字元透過

。charCodeAt

方法轉為 char code 儲存,讀取字型資訊時再透過

String。fromCharCode

轉回來。原來的字串變成了數字型別的陣列,這樣就沒有特殊字元的問題了。最後,透過拼接文字並生成 JS 檔案來將原始的、利於人維護的字型檔案,轉成了編譯 JS 工作的模組。

藝術字!實現可複用控制檯的列印功能

其中 defs 就是這個字型對應的字義列表,codes 則是字型的 char code 陣列,所有的字型都被放在一個 JS 檔案中。

這裡提一下,第 3 行的

parsedFonts

就是遍歷所有原始字型檔案解析到的內容,因此得到這部分也是需要透過 NodeJS 的

fs

模組來遞迴讀取原始檔目錄下的字型檔案的。算是基操,就不用展開了。

由於這部分是可以提前解析編譯的,一旦生成了 JS 模組後就不會對 NodeJS 執行時有依賴,所以保證了其依然可以執行在瀏覽器中。

2。3。 字型的排版

我們的字型格式確定了,目標的渲染方式也確定了。最後就可以填充這部分的邏輯實現了。

具體排版上會遇到一些細節點,例如不等高字型的空行填充、最大行寬的換行判斷(需要使用者執行行寬),不過這些都是小點,處理也不太複雜。這裡可能介紹一下稍有特殊的一塊 —— 字間距調整。

我們知道,一些藝術字的傾斜程度可能很大,例如這個字元「1」:

藝術字!實現可複用控制檯的列印功能

如果按簡單的矩形型包圍盒來分配空間,大概會是下面這樣:

藝術字!實現可複用控制檯的列印功能

前後兩個字型,即使設定為最小間距(0),仍然會距離很遠,這樣就破壞了一定的顯示效果。例如上圖中我兩個包圍盒間距其實只有 1,但看起來就很大。我們實際希望的可能是下面這樣:

藝術字!實現可複用控制檯的列印功能

間距為 1 時,兩個字元「1」調整為在最近的地方間距為 1。如果要更寬的效果可以設定更多間距。這個處理起來主要就是需要算出最大的「擠壓空間」(即兩個盒子最大支援的交叉空間)。最開始渲染的時候說了,我們是按 console 出的行來儲存的與列印的,舉個例子,這個「1」高度為 8 ,所以渲染的時候就是一個 8 個元素的字串陣列:

藝術字!實現可複用控制檯的列印功能

渲染的時候直接

lines。forEach(l => console。log(l))

即可。

注意,為了便於讀者閱讀,上面的 lines 陣列內的字串我沒有加上轉義,它是不合法的!只是為了展示起來更便於閱讀理解,實際中不能這麼寫。

最大縮排(縮排這個詞不準確,但希望大家能夠理解那個意思)的計算只需要知道之前的每個 line 尾部對應有多少空格,同時需要再其後新新增字元每個 line 前面又分別有多少空格,綜合兩者,再遍歷所有的 line 取一個最小值即可:

藝術字!實現可複用控制檯的列印功能

最後

calcIndent

方法返回的就是新字元需要向前縮排(或者說縮緊)的值。最後渲染的時候根據這個值來調整每行連線時新增的空格數即可。

捎帶一提,之前的字型格式 load 進來會被轉換為類似字典的格式 —— 字義作為 key,字型等一系列屬性作為 value:

藝術字!實現可複用控制檯的列印功能

這樣遍於

split

完使用者傳入的字串後,更簡單的索引到對應的字型和字型資訊。

2。4。 其他

當然,其他還會有一些工作,包括

支援顏色

支援返回排版完的 lines 讓使用者自己渲染

支援使用者自定義調整字間距

這些目前實現上遇到的問題不大,篇幅原因也就不說了。具體的程式碼可以在 Github 上看到。

3。 總結

實現可複用的控制檯“藝術字”功能,總的來說並沒有太多複雜的點,整體的流程模型就是

生成字型庫 ——> 字型排版 ——> 渲染文字

這對於前端來說應該是非常好理解的。

做這個專案也確實是自己在工作中希望給一些庫加上這種 logo 或者 banner 展示,但每次重複枯燥的工作確實令人反感。所以想了下可行性之後就搞了 yoo-hoo 這麼個小玩意兒,如果大家也遇到類似的問題,希望能有所幫助。

藝術字!實現可複用控制檯的列印功能

4。 最後

目前 yoo-hoo@1。0。x 內建了一套 26 個字母(A-Z)、10 個數字(0-9)、

·

*

-

|

這些字元的字型庫。

考慮到單一的字型和有限的字型量肯定不能滿足所有需求,所以開發時程式碼結構就留下了支援外部擴充套件的模式。

後續可以把 2。2 節中的字型原始檔解析工具獨立出來,支援使用者「手繪」自己的字型,用工具生成對應格式後,將字型的 JS 模組傳入

yo

方法中作為擴充套件字型載入。

字型原始檔的「手繪」雖有成本,但所見即所得,編寫難度不大 同時也算是一勞永逸。

原作者姓名:alienzhou

原出處:segmentfault

原文連結:如何實現可複用的控制檯“藝術字”列印功能_精益前端 - SegmentFault 思否

標簽: 字型  渲染  排版  js