本文首發於 vivo互聯網技術 微信公衆號
連接: https://mp.weixin.qq.com/s/39NCyZvm8EYiJ-pEEtjxGw
做者:何彥軍css
目前在移動端開發的展現界面中,若是一段文本的數量過長,受限於屏幕的寬高等因素,有可能不能徹底顯示,這個時候就會把溢出的文本顯示成省略號。html
最近就親身經歷了一系列相似的需求,因而這裏作個總結和記錄。vue
首先一個最基本的需求就是當文本超過一行最大寬度時,超出的部分變爲省略號,以下圖所示。git
這個功能比較基礎,只用css就能夠實現,以下圖所示代碼塊。github
但是有時候產品同窗但願顯示的文本能夠再多一點,因而就有了多行文本溢出顯示省略號的需求,以下圖所示。web
這個功能也能夠經過css實現,以下圖代碼塊所示。canvas
這裏用到了webkit的css擴展屬性,所以適用於webkit瀏覽器及移動端,而且在兼容性方面也有些影響,可是隻要不是特別老舊的機器,仍是徹底可以支持的。瀏覽器
在支持了多行文本溢出顯示省略號的功能以後,產品同窗又發現了體驗不友好的點,以下圖所示。文本在第二行開頭處就結束了,這就致使第二行大部分是空白的,影響了美觀度。微信
所以,產品同窗提出了一個新需求:ide
當文本沒有超過第x行的一半時,則按第x-1行溢出顯示省略號的方式展現;(第1行除外)
當文本超過第x行的一半但沒有超過第x行時,則正常展現;
這就須要計算出文本實際佔用的寬度才能選擇採用哪一種展現方式。
查找資料得知,canvas提供了一個measureText的方法,該方法的返回包含一個對象,這個對象裏包含了以像素計的指定字體寬度。
若是須要在文本顯示以前,就瞭解文本的寬度,那麼可使用該方法。
上面的代碼顯示效果以下:
因而能夠基於canvas能力來實現這個功能,大概的流程圖以下圖所示。
這裏最關鍵的是要計算出每一行能夠顯示多少文本,利用canvas的measureText方法,能夠達到這個效果,僞代碼以下所示。
雖然canvas能夠計算出文本顯示的寬度,而且兼容性和性能都還不錯,可是當某一行末尾出現特殊符號或者是英文單詞時,就會出現預期外的狀況。
瀏覽器實際渲染出來的時候,若是末尾有特殊符號時會連同前面的字符一塊兒換行,而若是末尾有英文單詞時也會將這個英文單詞換行展現。
但經過canvas計算出來的結果,會致使每一行的文本增多了,從而跟預期的展現效果有出入。
所以,這種方案只能適用於文本中不包含特殊符號和英文單詞的場景。
一段時間後,產品同窗感受展現那麼一段文本有點兒單調,因而又提出了一個進階版的需求:
文本的首行開頭須要縮進或者能夠配置一個圖標;
順帶給出了一個參考示例,以下圖所示。
因爲以前沒有遇到過相似的需求,因而開始google這個問題,通過海量的檢索,終於發現了該問題實現的方案。
原來網上也有不少朋友遇到了這樣的需求,並專門寫了單獨的組件來使用,好比:
HeyUI:https://www.heyui.top/component/other/textellipsis
vue-text-ellipsis:https://github.com/Luobata/vue-text-ellipsis
它們的思路都是經過最終展現的實際高度是否超過預期的容器高度來判斷是否須要刪減文本。其流程圖大概以下圖所示。
就這樣,經過現成的組件就解決了一個難題。
然鵝,本覺得需求已經告一段落了,哪知產品同窗又開始了體驗上的深度挖掘。
她們認爲,展現的文本樣式不該該都是同樣的。
有些文本表達的意思可能比較重要,這就須要重點引發用戶的注意。
而有些文本表達的意思可能重要程度通常,這就不須要用戶注意。
因而乎她們又提出了一個經過高亮文原本提高用戶體驗的需求:
比方說,獲取到下面一段文本,它要顯示出入下圖所示的那樣高亮效果。
因爲文本高亮須要經過標籤將文本包裹起來並添加高亮樣式才能實現,而以前的組件是經過v-text的方式實現的,所以這裏不能直接使用,須要將組件改形成v-html的方式插入才能夠。
假如經過v-html插入文本,而且設置了em標籤的樣式,那麼就會有一個問題,組件是經過循環剔除最後一個字符直到實際高度小於容器高度來實現展現功能的,這就有可能截掉標籤字符,致使最後的展現有異常。
因此,在截取文本的時候還須要作一些處理,流程圖以下圖所示。
到這裏,已經實現文本的一種高亮形式了,可是假若有好幾個部分的文本須要高亮且高亮的樣式還各不相同,這又要怎麼解決呢?
一種思路是,經過幾種不一樣名稱的標籤分別包裹須要高亮的文本,每一種標籤會對應一種高亮樣式,這樣的話,在得到源文本後,首先經過詞法分析將源文本中的標籤解析出來,後面的流程就跟上圖步驟1後面的流程相似了。