基于getClientRects()實現行內元素多行文本展開收起(包括省略)的功能

一般的省略實現方式

經常會遇到多行文本省略變成...的形式的開發(fā)要求琢唾,并且基于用戶體驗的角度出發(fā),還需要對于文本有對應展開與收起的操作按鈕桅滋。
1.使用css屬性

overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;

或者

overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;

都只是實現了...的省略功能慧耍,達不到需求的目的。
2.通過js都是判斷固定的長度(但是div或者span往往長度不固定)切割省略丐谋,總是會有一個字符或者兩個字符留白或者部分機型剛好換行的芍碧,沒有很好實現需求。


通過js切割固定的長度.png

基于getClientRects()的實現方式

1.getClientRects()的作用就是獲取元素占據頁面的所有矩形區(qū)域号俐。

var rect = document.getElementById('#rect');
console.log(rect)
//bottom: 58 height: 19 left: 20 right: 330.578125 top: 39 width: 310.578125 x: 20 y: 39

返回值是ClientRect對象集合泌豆,該對象是與該元素相關的CSS邊框。每個ClientRect對象包含一組描述該邊框的只讀屬性——left吏饿、top踪危、right和bottom蔬浙,單位為像素,這些屬性值是相對于視口的top-left的贞远。即使當表格的標題在表格的邊框外面畴博,該標題仍會被計算在內。

起初蓝仲,微軟打算讓這個方法給文本的每一行都返回一個TextRectangle俱病,但是,CSSOM工作草案規(guī)定它應該給每個邊框返回一個ClientRect袱结。因此亮隙,對于行內元素這兩個定義是相同的,但是對于塊級元素垢夹,Mozilla只會返回一個矩形溢吻。(譯者注:對于行內元素,元素內部的每一行都會有一個邊框促王;對于塊級元素,如果里面沒有其他元素硼砰,一整塊元素只有一個邊框)欣硼。

2.行內元素通過getClientRects()就能獲取到當前文本多少行题翰,只要通過遍歷,每次減少1個長度(br標簽減少5)诈胜,不斷計算是否是所需要的行數即可(例如文本5行,我需要3行省略焦匈,只要讓對于的span剛好是3行就可以,這樣就得到一個省略的文本了)
基于jQuery的方法實現如下:
html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>完美版本的展開收起...</title>
    <style>
      *{margin: 0;
      padding: 0;}
      div {
        width: 700px;
        height: auto;
        font-size: 14px;
        color: #333;
        background-color: #fafafa;
        padding: 20px;
      }
      span.text-fold {
        display: inline;
        color: #4293f4;
        cursor: pointer;
      }
      span.col-333 {
        color: #333;
        font-size: 14px;
        line-height: 20px;
      }
    </style>
  </head>
  <body>
    <div>
      <span class="">春 ——朱自清:<br /></span>
      <span class="break-word col-333" id="txt" style="display: inline;"
        >&nbsp;&nbsp;&nbsp;&nbsp;盼望著缓熟,盼望著累魔,東風來了,春天的腳步近了够滑。<br>
        一切都像剛睡醒的樣子,欣欣然張開了眼彰触。山朗潤起來了,水漲起來了分蓖,太陽的臉紅起來了。<br>
        &nbsp;&nbsp;&nbsp;&nbsp;小草偷偷地從土地里鉆出來么鹤,嫩嫩的,綠綠的午磁。園子里,田野里,瞧去衙熔,一大片一大片滿是的。坐著框咙,躺著痢甘,打兩個滾喇嘱,踢幾腳球塞栅,賽幾趟跑,捉幾回迷藏作烟。風輕悄悄的砾医,草軟綿綿的。<br>
        &nbsp;&nbsp;&nbsp;&nbsp;桃樹如蚜,杏樹,梨樹探赫,你不讓我兴猩,我不讓你,都開滿了花趕趟兒。紅的像火讨勤,粉的像霞,白的像雪潭千。花里帶著甜味屉来;閉了眼狈癞,樹上仿佛已經滿是桃兒,杏兒蝶桶,梨兒≌媸花下成千成百的蜜蜂嗡嗡的鬧著,大小的蝴蝶飛來飛去战秋。野花遍地是:雜樣兒讨韭,有名字的,沒名字的拐袜,散在草叢里像眼睛像星星,還眨呀眨的蹬铺。<br>
        &nbsp;&nbsp;&nbsp;&nbsp;“吹面不寒楊柳風”甜攀,不錯的秋泄,像母親的手撫摸著你规阀,風里帶著些新翻的泥土的氣息,混著青草味兒歧胁,還有各種花的香,都在微微潤濕的空氣里醞釀屠缭。鳥兒將巢安在繁花嫩葉當中崭参,高興起來了,呼朋引伴的賣弄清脆的歌喉何暮,唱出婉轉的曲子,跟清風流水應和著跨新。牛背上牧童的短笛贰军,這時候也成天嘹亮的響著。<br>
        &nbsp;&nbsp;&nbsp;&nbsp;雨是最尋常的词疼,一下就是三兩天帘腹。可別惱舵盈∏蚧看,像牛毛筒愚,像花針,像細絲句伶,密密地斜織著陆淀,人家屋頂上全籠著一層薄煙。樹葉卻綠得發(fā)亮楚堤,小草也青得逼你的眼。傍晚時候身冬,上燈了,一點點黃暈的光拗小,烘托出一片安靜而和平的夜樱哼。在鄉(xiāng)下,小路上搅幅,石橋邊,有撐著傘慢慢走著的人息裸,地里還有工作的農民沪编,披著蓑戴著笠。他們的房屋稀稀疏疏的访圃,在雨里靜默著相嵌。<br>
        &nbsp;&nbsp;&nbsp;&nbsp;天上的風箏漸漸多了,地上的孩子也多了饭宾。城里鄉(xiāng)下,家家戶戶徽鼎,老老小小性湿,也趕趟似的,一個個都出來了肤频。舒活舒活筋骨,抖擻抖擻精神汁雷,各做各的一份事兒去。
        &nbsp;&nbsp;&nbsp;&nbsp;“一年之計在于春”挖藏,剛起頭兒厢漩,有的是功夫,有的是希望溜嗜。<br>
        &nbsp;&nbsp;&nbsp;&nbsp;春天像剛落地的娃娃,從頭到腳都是新的辟躏,它生長著土全。<br>
        &nbsp;&nbsp;&nbsp;&nbsp;春天像小姑娘,花枝招展的瑞凑,笑著走著概页。<br>
        &nbsp;&nbsp;&nbsp;&nbsp;春天像健壯的青年,有鐵一般的胳膊和腰腳绰沥,領著我們向前去贺待。</span
      >
      <script src="http://libs.baidu.com/jquery/1.11.1/jquery.min.js"></script>
      <script src="../js/rectOmitText.js"></script>
      <script>
        $(function(){
          $('#txt').rectOmitText({
            line: 5,
            foldText: '隱藏',
            unfoldText: '更多',
            foldClass: 'text-fold'
          });
        })
      </script>
    </div>
  </body>
</html>

基于jquery實現的rectOmitText.js:

/*
 * getClientRects()只是支持行內元素麸塞,非行內元素不支持該方法
 * unfoldText 展開文本
 * foldText 收起文本
 * unfoldClass 展開類名
 * foldClass 收起類名
 * line 多少行省略
 * color 默認樣式顏色
 */

(function ($) {
  $.fn.rectOmitText = function (options) {
    if ($(this).css("display") != "inline") {
      console.warn(
        "該方法不支持非行內(inline)元素展開收起以及省略,奥此!請把對應的元素轉為inline元素"
      );
      return false;
    }

    var defaluts = {
      unfoldText: "展開",
      foldText: "收起",
      unfoldClass: "",
      foldClass: "",
      line: 1,
      color: "style='color: #2a68c9;'",
    };
    
    var opt = $.extend(defaluts, options);
    var txtHtml = $(this).html(); //所有文本
    var omitHtml = $(this).html(); //省略文本
    var rect = $(this)[0].getClientRects(); //獲取元素占據頁面的所有矩形區(qū)域
    console.log(rect)
    var line = getLineLen(rect); //文本真實的行數
    //展開顯示文本
    var unfold = opt.unfoldClass
      ? "<span>... </span><span class='rect-unfold " +
        opt.unfoldClass +
        "'>" +
        opt.unfoldText +
        "</span>"
      : "<span>... </span><span " +
        opt.color +
        " class='rect-unfold " +
        opt.unfoldClass +
        "'>" +
        opt.unfoldText +
        "</span>";
    //收起顯示文本
    var fold = opt.foldClass
      ? "<span class='rect-fold " +
        opt.foldClass +
        "'>" +
        opt.foldText +
        "</span>"
      : "<span " +
        opt.color +
        "class='rect-fold " +
        opt.foldClass +
        "'>" +
        opt.foldText +
        "</span>";

    if (line && line == 1) {
      console.warn("標簽文本內容只有一行雁比,不作省略!");
      return false;
    }

    if (opt.line >= line) {
      console.warn("傳入的省略行數大于文本行數蠢终,不作省略");
      return false;
    }

    //行數大于5行,顯示... 展開按鈕
    while (line > opt.line) {
      var step = 1;
      if (/<br\/>$/.test(omitHtml)) {
        //回退的時候程奠,如果碰到換行要整體替換
        step = 5;
      }

      //每次減少文本數組最后以為參數(br標簽直接減少整個br標簽的長度)
      omitHtml = omitHtml.slice(0, -step);
      txt.innerHTML = omitHtml + unfold;

      //更新行數
      line = getLineLen($(this)[0].getClientRects());
      if (omitHtml.length <= 0) {
        //強制停止循環(huán)
        break;
      }
    }

    //展開點擊
    $("#txt").on("click", "span.rect-unfold", function () {
      $("#txt").html(txtHtml + fold);
    });

    //收起點擊
    $("#txt").on("click", "span.rect-fold", function () {
      $("#txt").html(omitHtml + unfold);
    });

    function getLineLen(arr) {
      //獲取當前文本真實的行數祭钉,如果是<br>符號getClientRects()方法也會變成一個區(qū)域
      var line = 0;
      var bottom = 0;
      for (var i = 0; i < arr.length; i++) {
        if (arr[i].bottom != bottom) {
          bottom = arr[i].bottom;
          line++;
        }
      }
      return line;
    }
  };
})(jQuery);

隱藏效果:


隱藏.png

展開效果


展開.png

注意

getClientRects()的方式僅僅支持行內元素(inline),塊級元素或者行內塊級元素都只是識別為一個矩形區(qū)域慌核,需要使用先把對應的標簽轉化為行內元素(inline)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末遂铡,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子扒接,更是在濱河造成了極大的恐慌,老刑警劉巖碱呼,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宗侦,死亡現場離奇詭異,居然都是意外死亡姑裂,警方通過查閱死者的電腦和手機男旗,發(fā)現死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來茴厉,“玉大人什荣,你說我怎么就攤上這事〉九溃” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵泞辐,是天一觀的道長。 經常有香客問我吹缔,道長锯茄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任晚碾,我火速辦了婚禮喂急,結果婚禮上,老公的妹妹穿的比我還像新娘廊移。我一直安慰自己,他們只是感情好懂诗,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布苗膝。 她就那樣靜靜地躺著,像睡著了一般辱揭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上侯繁,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天泡躯,我揣著相機與錄音丽焊,去河邊找鬼。 笑死写穴,一個胖子當著我的面吹牛雌贱,可吹牛的內容都是我干的偿短。 我是一名探鬼主播馋没,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼勾怒!你這毒婦竟也來了声旺?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤鉴扫,失蹤者是張志新(化名)和其女友劉穎澈缺,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體谍椅,經...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年锁施,在試婚紗的時候發(fā)現自己被綠了杖们。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡姥饰,死狀恐怖孝治,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情岂座,我是刑警寧澤杭措,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站手素,受9級特大地震影響瘩蚪,放射性物質發(fā)生泄漏稿黍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一拱礁、第九天 我趴在偏房一處隱蔽的房頂上張望辕漂。 院中可真熱鬧,春花似錦鸯乃、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至陋守,卻和暖如春利赋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背媚送。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工塘偎, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留疗涉,地道東北人吟秩。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓峰尝,卻偏偏與公主長得像,于是被迫代替她去往敵國和親武学。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內容