多行文本內(nèi)容超出顯示省略號(hào)... 的終極解決方案
大廠技術(shù)??高級(jí)前端??Node進(jìn)階
點(diǎn)擊上方?程序員成長(zhǎng)指北,關(guān)注公眾號(hào)
回復(fù)1,加入高級(jí)Node交流群

作者:夢(mèng)想敲木魚
https://juejin.cn/post/7026655351004987400
最近遇到一個(gè)貌似很簡(jiǎn)單,但寫起來也不簡(jiǎn)單的問題。對(duì)于多行文字,超出...顯示。通過css可以實(shí)現(xiàn),但受限于瀏覽器兼容問題,有時(shí)候還需要依賴JS來實(shí)現(xiàn)。通過js實(shí)現(xiàn),就需要考慮到文字大小,中英文、數(shù)子、標(biāo)點(diǎn)符號(hào)所對(duì)應(yīng)的字節(jié)長(zhǎng)度不一致,如果考慮的不全面,對(duì)于不同的文字內(nèi)容,總會(huì)有點(diǎn)差距。
首先,我們需要了解,中文漢字,英文字母,數(shù)字以及特殊符號(hào)所占的字節(jié)長(zhǎng)度是不一樣的,如果需要計(jì)算準(zhǔn)確,就不能按照字符串的元素個(gè)數(shù)去截取,把它們換算成字節(jié)數(shù)來截取,準(zhǔn)確度更高。所以,我們需要一個(gè)獲取字符串字節(jié)長(zhǎng)度的方法:
????????function?bitCompute(content)?{
????????????var?total?=?0,
????????????????len?=?arguments[0].length?||?0
????????????for?(var?i?=?0;?i?????????????????if?(content[i].charCodeAt()?>?255)?{
????????????????????total?+=?2;
????????????????}?else?{
????????????????????total?+=?1;
????????????????}
????????????}
????????????return?total
????????}
復(fù)制代碼
對(duì)于要截取多少內(nèi)容的字節(jié)數(shù),我們需要知悉能放入容器內(nèi)的字節(jié)數(shù)與總字節(jié)數(shù)的比例,展示字節(jié)數(shù)/總字節(jié)數(shù) = offsetWidth / scrollWidth:
?????????function?complate()?{
????????????var?offsetWidth?=?el.offsetWidth;
????????????var?scrollWidth?=?el.scrollWidth;
????????????var?gap?=?scrollWidth?-?offsetWidth;
????????????var?percent?=?Math.floor(offsetWidth?/?scrollWidth?*?1e3)?/?1e3;
????????????return?{
????????????????gap:?gap,
????????????????percent:?percent
????????????}
????????}
復(fù)制代碼
根據(jù)計(jì)算得出的數(shù)據(jù),我們就可以操作字符串了
????????function?cut(content)?{
????????????el.innerHTML?=?content;
????????????var?info?=?complate(),
????????????????percent?=?info.percent;
????????????var?total?=?bitCompute(content).total;
????????????var?showLen?=?+(total?*?percent).toFixed(0)?-?cfg.placeholder;
????????????content?=?bitCompute(content,?showLen).content;
????????????return?content?+?cfg.padding;
????????}
????????
????????function?bitCompute(content,?maxLen)?{
????????????var?total?=?0,
????????????????len?=?arguments[0].length?||?0,
????????????????outContent?=?'';
????????????for?(var?i?=?0;?i?????????????????if?(content[i].charCodeAt()?>?255)?{
????????????????????total?+=?2;
????????????????}?else?{
????????????????????total?+=?1;
????????????????}
????????????????if?(maxLen?&&?total?>?maxLen)?{
????????????????????break;
????????????????}
????????????????outContent?+=?content[i];
????????????}
????????????return?{
????????????????total:?total,
????????????????content:?outContent
????????????}
????????}
復(fù)制代碼
當(dāng)然文字展示的多少,也是和字體大小相關(guān)的,所以我們也需要把字體大小的因素考慮到,而且作為一個(gè)工作方法,本身就不應(yīng)該頁面中的元素有關(guān)聯(lián),所以我們應(yīng)該在方法中自己創(chuàng)建元素,放入內(nèi)容,計(jì)算offsetWidth和scrollWidth
??????function?cutFactory(opt)?{
????????var?cfg?=?{
????????????padding:?opt.padding?||?"...",
????????????classList:?opt.classList?||?[],
????????????style:?opt.style?||?{},
????????????debug:?opt.debug
????????};
????????cfg.placeholder?=?bitCompute(cfg.padding).total;
????????var?el?=?doc.createElement("span");
????????el.className?=?cfg.classList.join("?");
????????var?customStyles?=?[];
????????for?(var?styleKey?in?cfg.style)?{
????????????if?(cfg.style.hasOwnProperty(styleKey))?{
????????????????customStyles.push(styleKey?+?":"?+?cfg.style[styleKey]);
????????????}
????????}
????????el.style.cssText?=?"position:absolute;left:0;top:0;background:transparent;color:transparent;height:100%;white-space:nowrap;overflow:visible;border:0;"?+?(cfg.debug???"background:white;color:red;"?:?"")?+?customStyles.join(";");
????????var?div?=?doc.createElement("div");
????????div.appendChild(el);
????????div.style.cssText?=?"width:99%;min-height:50px;line-height:50px;position:absolute;left:3px;top:3px;overflow:hidden;outline:0;background:transparent;"?+?(cfg.debug???"outline:1px?solid?red;background:black;"?:?"");
????????doc.body.appendChild(div);
????????var?css?=?win.getComputedStyle(el);
????????cfg.fontSize?=?parseFloat(css.fontSize)?||?16;
????????
?????????return?function?(content)?{
????????????el.innerHTML?=?content;
????????????var?out?=?{
????????????????flag:?false,
????????????????cut:?'',
????????????????all:?content,
????????????????last:?content
????????????}
????????????if?(complate().gap?>?0)?{
????????????????out.flag?=?true,
????????????????out.last?=?out.cut?=?cut(content)
????????????}
????????????return?out
????????}
?????}
復(fù)制代碼
最后,再暴露一個(gè)方法,方便使用者調(diào)用。為了性能考慮,不創(chuàng)建過多dom元素,我們可以緩存一下字體大小和容器寬度相同的截取方法
????function?subStringEL(name,?fontSize,?width)?{
????????this.subStringELFns?||?(this.subStringELFns?=?{});
????????var?key?=?'key_'?+?fontSize?+?'_'?+?width;
????????var?fn?=?this.subStringELFns[key];
????????if?(!fn)?{
????????????fn?=?this.subStringELFns[key]?=?cutFactory({
????????????????style:?{
????????????????????'font-size':?fontSize,
????????????????????'width':?width
????????????????}
????????????})
????????}
????????return?fn(name);
????}
復(fù)制代碼
這樣就完美的解決了多行超出...顯示的問題了,兼容性很好,而且也能準(zhǔn)確截取,靈活方便。希望能幫助到受該問題困擾的同仁,內(nèi)容中如有不正確之處,煩請(qǐng)指正,不勝感激! 另外附注源碼地址:
github地址:https://github.com/18822600748/MyJSFactory/blob/main/src/subStrByWidth.js[1
我組建了一個(gè)氛圍特別好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你對(duì)Node.js學(xué)習(xí)感興趣的話(后續(xù)有計(jì)劃也可以),我們可以一起進(jìn)行Node.js相關(guān)的交流、學(xué)習(xí)、共建。下方加 考拉 好友回復(fù)「Node」即可。
???“分享、點(diǎn)贊、在看” 支持一波??
