天天看點

淺談移動端過長文本溢出顯示省略号的實作方案

本文首發于 vivo網際網路技術 微信公衆号 

連結:

https://mp.weixin.qq.com/s/39NCyZvm8EYiJ-pEEtjxGw 作者:何彥軍

目前在移動端開發的展示界面中,如果一段文本的數量過長,受限于螢幕的寬高等因素,有可能不能完全顯示,這個時候就會把溢出的文本顯示成省略号。

最近就親身經曆了一系列類似的需求,于是這裡做個總結和記錄。

首先一個最基本的需求就是當文本超過一行最大寬度時,超出的部分變為省略号,如下圖所示。

淺談移動端過長文本溢出顯示省略号的實作方案

這個功能比較基礎,隻用css就可以實作,如下圖所示代碼塊。

淺談移動端過長文本溢出顯示省略号的實作方案

可是有時候産品同學希望顯示的文本可以再多一點,于是就有了多行文本溢出顯示省略号的需求,如下圖所示。

淺談移動端過長文本溢出顯示省略号的實作方案
淺談移動端過長文本溢出顯示省略号的實作方案

這個功能也可以通過css實作,如下圖代碼塊所示。

淺談移動端過長文本溢出顯示省略号的實作方案
淺談移動端過長文本溢出顯示省略号的實作方案

這裡用到了webkit的css擴充屬性,是以适用于webkit浏覽器及移動端,并且在相容性方面也有些影響,但是隻要不是特别老舊的機器,還是完全能夠支援的。

在支援了多行文本溢出顯示省略号的功能之後,産品同學又發現了體驗不友好的點,如下圖所示。文本在第二行開頭處就結束了,這就導緻第二行大部分是空白的,影響了美觀度。

淺談移動端過長文本溢出顯示省略号的實作方案

是以,産品同學提出了一個新需求:

  • 當文本沒有超過第x行的一半時,則按第x-1行溢出顯示省略号的方式展示;(第1行除外)
  • 當文本超過第x行的一半但沒有超過第x行時,則正常展示;
  • 當文本超過第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後面的流程類似了。