js如何实现当文本内容过长时,中间显示省略号...,两端正常展示

本文主要是介绍js如何实现当文本内容过长时,中间显示省略号...,两端正常展示,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前一阵做需求时,有个小功能实现起来废了点脑细胞,觉得可以记录一下。

产品的具体诉求是:用户点击按钮进入详情页面,详情页内的卡片标题内容过长时,标题的前后两端正常展示,中间用省略号...表示,并且鼠标悬浮后,展示全部内容。

关于鼠标悬浮展示全部内容的代码就不放在这里了,本文主要写关于实现中间省略号...的代码。

实现思路

  1. 获取标题盒子的真实宽度, 我这里用的是clientWidth;
  2. 获取文本内容所占的实际宽度;
  3. 根据文字的大小计算出每个文字所占的宽度;
  4. 判断文本内容的实际宽度是否超出了标题盒子的宽度;
  5. 通过文字所占的宽度累加之和与标题盒子的宽度做对比,计算出要截取位置的索引;
  6. 同理,文本尾部的内容需要翻转一下,然后计算索引,截取完之后再翻转回来;

代码

html代码

<div class="title" id="test">近日,银行纷纷下调大额存单利率,但银行定期存款仍被疯抢。银行理财经理表示:有意向购买定期存款要尽快,不确定利率是否会再降。</div>

css代码: 设置文本不换行,同时设置overflow:hidden让文本溢出盒子隐藏

.title {width: 640px;height: 40px;line-height: 40px;font-size: 14px;color: #00b388;border: 1px solid #ddd;overflow: hidden;/* text-overflow: ellipsis; */white-space: nowrap;/* box-sizing: border-box; */padding: 0 10px;
}

javascript代码:

获取标题盒子的宽度时要注意,如果在css样式代码中设置了padding, 就需要获取标题盒子的左右padding值。 通过getComputedStyle属性获取到所有的css样式属性对应的值, 由于获取的padding值都是带具体像素单位的,比如: px,可以用parseInt特殊处理一下。

获取盒子的宽度的代码,我当时开发时是用canvas计算的,但计算的效果不太理想,后来逛社区,发现了嘉琪coder大佬分享的文章,我这里就直接把代码搬过来用吧, 想了解的掘友可以直接滑到文章末尾查看。

判断文本内容是否超出标题盒子

 // 标题盒子dom
const dom = document.getElementById('test');// 获取dom元素的padding值
function getPadding(el) {const domCss = window.getComputedStyle(el, null);const pl = Number.parseInt(domCss.paddingLeft, 10) || 0;const pr = Number.parseInt(domCss.paddingRight, 10) || 0;console.log('padding-left:', pl, 'padding-right:', pr);return {left: pl,right: pr}
}
// 检测dom元素的宽度,
function checkLength(dom) {// 创建一个 Range 对象const range = document.createRange();// 设置选中文本的起始和结束位置range.setStart(dom, 0),range.setEnd(dom, dom.childNodes.length);// 获取元素在文档中的位置和大小信息,这里直接获取的元素的宽度let rangeWidth = range.getBoundingClientRect().width;// 获取的宽度一般都会有多位小数点,判断如果小于0.001的就直接舍掉const offsetWidth = rangeWidth - Math.floor(rangeWidth);if (offsetWidth < 0.001) {rangeWidth = Math.floor(rangeWidth);}// 获取元素padding值const { left, right } = getPadding(dom);const paddingWidth = left + right;// status:文本内容是否超出标题盒子;// width: 标题盒子真实能够容纳文本内容的宽度return {status: paddingWidth + rangeWidth > dom.clientWidth,width: dom.clientWidth - paddingWidth};
}

通过charCodeAt返回指定位置的字符的Unicode编码, 返回的值对应ASCII码表对应的值,0-127包含了常用的英文、数字、符号等,这些都是占一个字节长度的字符,而大于127的为占两个字节长度的字符。

截取和计算文本长度

// 计算文本长度,当长度之和大于等于dom元素的宽度后,返回当前文字所在的索引,截取时会用到。
function calcTextLength(text, width) {let realLength = 0;let index = 0;for (let i = 0; i < text.length; i++) {charCode = text.charCodeAt(i);if (charCode >= 0 && charCode <= 128) {realLength += 1;} else {realLength += 2 * 14; // 14是字体大小}// 判断长度,为true时终止循环,记录索引并返回if (realLength >= width) {index = i;break;}}return index;
}// 设置文本内容
function setTextContent(text) {const { status, width } = checkLength(dom);let str = '';if (status) {// 翻转文本let reverseStr = text.split('').reverse().join('');// 计算左右两边文本要截取的字符索引const leftTextIndex = calcTextLength(text, width);const rightTextIndex = calcTextLength(reverseStr, width);// 将右侧字符先截取,后翻转reverseStr = reverseStr.substring(0, rightTextIndex);reverseStr = reverseStr.split('').reverse().join('');// 字符拼接str = `${text.substring(0, leftTextIndex)}...${reverseStr}`;} else {str = text;}dom.innerHTML = str;
}

最终实现的效果如下:

3d514aaa9cd54d58b1889dee36612fc7.png

上面就是此功能的所有代码了,如果想要在本地试验的话,可以在本地新建一个html文件,复制上面代码就可以了。

下面记录下从社区内学到的相关知识:

  1. js判断文字被溢出隐藏的几种方法;
  2. JS获取字符串长度的几种常用方法,汉字算两个字节;

1、 js判断文字被溢出隐藏的几种方法

1. Element-plus这个UI框架中的表格组件实现的方案。

通过document.createRangedocument.getBoundingClientRect()这两个方法实现的。也就是我上面代码中实现的checkLength方法。

2. 创建一个隐藏的div模拟实际宽度

通过创建一个不会在页面显示出来的dom元素,然后把文本内容设置进去,真实的文本长度与标题盒子比较宽度,判断是否被溢出隐藏了。

function getDomDivWidth(dom) {const elementWidth = dom.clientWidth;const tempElement = document.createElement('div');const style = window.getComputedStyle(dom, null)const { left, right } = getPadding(dom); // 这里我写的有点重复了,可以优化tempElement.style.cssText = `position: absolute;top: -9999px;left: -9999px;white-space: nowrap;padding-left:${style.paddingLeft};padding-right:${style.paddingRight};font-size: ${style.fontSize};font-family: ${style.fontFamily};font-weight: ${style.fontWeight};letter-spacing: ${style.letterSpacing};`;tempElement.textContent = dom.textContent;document.body.appendChild(tempElement);const obj = {status: tempElement.clientWidth + right + left > elementWidth,width: elementWidth - left - right}document.body.removeChild(tempElement);return obj;
}

3. 创建一个block元素来包裹inline元素

这种方法是在UI框架acro design vue中实现的。外层套一个块级(block)元素,内部是一个行内(inline)元素。给外层元素设置溢出隐藏的样式属性,不对内层元素做处理,这样内层元素的宽度是不变的。因此,通过获取内层元素的宽度和外层元素的宽度作比较,就可以判断出文本是否被溢出隐藏了。

// html代码
<div class="title" id="test"><span class="content">近日,银行纷纷下调大额存单利率,但银行定期存款仍被疯抢。银行理财经理表示:有意向购买定期存款要尽快,不确定利率是否会再降。</span>
</div>// 创建一个block元素来包裹inline元素
const content = document.querySelector('.content');
function getBlockDomWidth(dom) {const { left, right } = getPadding(dom);console.log(dom.clientWidth, content.clientWidth)const obj = { status: dom.clientWidth < content.clientWidth + left + right,width: dom.clientWidth - left - right}return obj;
}

4. 使用canvas中的measureText方法和TextMetrics对象来获取元素的宽度

通过Canvas 2D渲染上下文(context)可以调用measureText方法,此方法会返回TextMetrics对象,该对象的width属性值就是字符占据的宽度,由此也能获取到文本的真实宽度,此方法有弊端,比如说兼容性,精确度等等。

// 获取文本长度
function getTextWidth(text, font = 14) {const canvas = document.createElement("canvas");const context = canvas.getContext("2d")context.font = fontconst metrics = context.measureText(text);return metrics.width
}

5. 使用css实现

代码如下: css部分

.con {font-size: 14px;color: #666;width: 600px;margin: 50px auto;border-radius: 8px;padding: 15px;overflow: hidden;resize: horizontal;box-shadow: 20px 20px 60px #bebebe, -20px -20px 60px #ffffff;
}.wrap {position: relative;line-height: 2;height: 2em;padding: 0 10px;overflow: hidden;background: #fff;margin: 5px 0;
}.wrap:nth-child(odd) {background: #f5f5f5;
}.title {display: block;position: relative;background: inherit;text-align: justify;height: 2em;overflow: hidden;top: -4em;
}.txt {display: block;max-height: 4em;
}
.title::before{content: attr(title);width: 50%;float: right;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;direction: rtl;
}

html部分

<ul class="con"><li class="wrap"><span class="txt">CSS 实现优惠券的技巧 - 2021-03-26</span><span class="title" title="CSS 实现优惠券的技巧 - 2021-03-26">CSS 实现优惠券的技巧 - 2021-03-26</span></li><li class="wrap"><span class="txt">CSS 测试标题,这是一个稍微有点长的标题,超出一行以后才会有title提示,标题是 实现优惠券的技巧 - 2021-03-26</span><span class="title" title="CSS 测试标题,这是一个稍微有点长的标题,超出一行以后才会有title提示,标题是 实现优惠券的技巧 - 2021-03-26">CSS测试标题,这是一个稍微有点长的标题,超出一行以后才会有title提示,标题是 实现优惠券的技巧 - 2021-03-26</span></li><li class="wrap"><span class="txt">CSS 拖拽?</span><span class="title" title="CSS 拖拽?">CSS 拖拽?</span></li><li class="wrap"><span class="txt">CSS 文本超出自动显示title</span><span class="title" title="CSS 文本超出自动显示title">CSS 文本超出自动显示title</span></li>
</ul>

思路解析:

  1. 文字内容的父级标签li设置line-height: 2;overflow: hidden;height: 2em;,因此 li 标签的高度是当前元素字体大小的2倍,行高也是当前字体大小的2倍,同时内容若溢出则隐藏。

  2. li 标签内部有两个 span 标签,二者的作用分别是:类名为.txt的标签用来展示不需要省略号时的文本,类名为.title用来展示需要省略号时的文本,具体是如何实现的请看第五步。

  3. .title设置伪类before,将伪类宽度设置为50%,搭配浮动float: right;,使得伪类文本内容靠右,这样设置后,.title和伪类就会各占父级宽度的一半了。

  4. .title标签设置text-align: justify;,用来将文本内容和伪类的内容两端对齐。

  5. 给伪类before设置文字对齐方式direction: rtl;,将伪类内的文本从右向左流动,即right to left,再设置溢出省略的css样式就可以了。

  6. .title标签设置了top: -4em,.txt标签设置max-height: 4em;这样保证.title永远都在.txt上面,当内容足够长,.txt文本内容会换行,导致高度从默认2em变为4em,而.title位置是-4em,此时正好将.txt覆盖掉,此时显示的就是.title标签的内容了。

知识点:text-align: justify;

  • 文本的两端(左边和右边)都会与容器的边缘对齐。
  • 为了实现这种对齐,浏览器会在单词之间添加额外的空间。这通常意味着某些单词之间的间距会比其他单词之间的间距稍大一些。
  • 如果最后一行只有一个单词或少数几个单词,那么这些单词通常不会展开以填充整行,而是保持左对齐

需要注意的是,text-align: justify; 主要用于多行文本。对于单行文本,这个值的效果与 text-align: left; 相同,因为单行文本无法两端对齐。

2、JS获取字符串长度的几种常用方法

1. 通过charCodeAt判断字符编码

通过charCodeAt获取指定位置字符的Unicode编码,返回的值对应ASCII码表对应的值,0-127包含了常用的英文、数字、符号等,这些都是占一个字节长度的字符,而大于127的为占两个字节长度的字符。

function calcTextLength(text) {let realLength = 0;for (let i = 0; i < text.length; i++) {charCode = text.charCodeAt(i);if (charCode >= 0 && charCode <= 128) {realLength += 1;} else {realLength += 2;}}return realLength;
}

2. 采取将双字节字符替换成"aa"的做法,取长度

function getTextWidth(text) {return text.replace(/[^\x00-\xff]/g,"aa").length;
};

 

 

这篇关于js如何实现当文本内容过长时,中间显示省略号...,两端正常展示的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1031890

相关文章

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

RedHat运维-Linux文本操作基础-AWK进阶

你不用整理,跟着敲一遍,有个印象,然后把它保存到本地,以后要用再去看,如果有了新东西,你自个再添加。这是我参考牛客上的shell编程专项题,只不过换成了问答的方式而已。不用背,就算是我自己亲自敲,我现在好多也记不住。 1. 输出nowcoder.txt文件第5行的内容 2. 输出nowcoder.txt文件第6行的内容 3. 输出nowcoder.txt文件第7行的内容 4. 输出nowcode

JAVA读取MongoDB中的二进制图片并显示在页面上

1:Jsp页面: <td><img src="${ctx}/mongoImg/show"></td> 2:xml配置: <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001

通过SSH隧道实现通过远程服务器上外网

搭建隧道 autossh -M 0 -f -D 1080 -C -N user1@remotehost##验证隧道是否生效,查看1080端口是否启动netstat -tuln | grep 1080## 测试ssh 隧道是否生效curl -x socks5h://127.0.0.1:1080 -I http://www.github.com 将autossh 设置为服务,隧道开机启动

据阿谱尔APO Research调研显示,2023年全球髓内钉市场销售额约为4.7亿美元

根据阿谱尔 (APO Research)的统计及预测,2023年全球髓内钉市场销售额约为4.7亿美元,预计在2024-2030年预测期内将以超过3.82%的CAGR(年复合增长率)增长。 髓内钉市场是指涉及髓内钉制造、分销和销售的行业。髓内钉是一种用于整形外科手术的医疗器械,用于稳定长骨骨折,特别是股骨、胫骨和肱骨。髓内钉通常由不銹钢或钛等材料制成,并插入骨的髓管中,以在愈合过程中提供结构支

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测 目录 时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测基本介绍程序设计参考资料 基本介绍 MATLAB实现LSTM时间序列未来多步预测-递归预测。LSTM是一种含有LSTM区块(blocks)或其他的一种类神经网络,文献或其他资料中LSTM区块可能被描述成智能网络单元,因为

vue项目集成CanvasEditor实现Word在线编辑器

CanvasEditor实现Word在线编辑器 官网文档:https://hufe.club/canvas-editor-docs/guide/schema.html 源码地址:https://github.com/Hufe921/canvas-editor 前提声明: 由于CanvasEditor目前不支持vue、react 等框架开箱即用版,所以需要我们去Git下载源码,拿到其中两个主

android一键分享功能部分实现

为什么叫做部分实现呢,其实是我只实现一部分的分享。如新浪微博,那还有没去实现的是微信分享。还有一部分奇怪的问题:我QQ分享跟QQ空间的分享功能,我都没配置key那些都是原本集成就有的key也可以实现分享,谁清楚的麻烦详解下。 实现分享功能我们可以去www.mob.com这个网站集成。免费的,而且还有短信验证功能。等这分享研究完后就研究下短信验证功能。 开始实现步骤(新浪分享,以下是本人自己实现

js+css二级导航

效果 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Con

基于Springboot + vue 的抗疫物质管理系统的设计与实现

目录 📚 前言 📑摘要 📑系统流程 📚 系统架构设计 📚 数据库设计 📚 系统功能的具体实现    💬 系统登录注册 系统登录 登录界面   用户添加  💬 抗疫列表展示模块     区域信息管理 添加物资详情 抗疫物资列表展示 抗疫物资申请 抗疫物资审核 ✒️ 源码实现 💖 源码获取 😁 联系方式 📚 前言 📑博客主页: