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

相关文章

使用Python实现IP地址和端口状态检测与监控

《使用Python实现IP地址和端口状态检测与监控》在网络运维和服务器管理中,IP地址和端口的可用性监控是保障业务连续性的基础需求,本文将带你用Python从零打造一个高可用IP监控系统,感兴趣的小伙... 目录概述:为什么需要IP监控系统使用步骤说明1. 环境准备2. 系统部署3. 核心功能配置系统效果展

Python实现微信自动锁定工具

《Python实现微信自动锁定工具》在数字化办公时代,微信已成为职场沟通的重要工具,但临时离开时忘记锁屏可能导致敏感信息泄露,下面我们就来看看如何使用Python打造一个微信自动锁定工具吧... 目录引言:当微信隐私遇到自动化守护效果展示核心功能全景图技术亮点深度解析1. 无操作检测引擎2. 微信路径智能获

Python中pywin32 常用窗口操作的实现

《Python中pywin32常用窗口操作的实现》本文主要介绍了Python中pywin32常用窗口操作的实现,pywin32主要的作用是供Python开发者快速调用WindowsAPI的一个... 目录获取窗口句柄获取最前端窗口句柄获取指定坐标处的窗口根据窗口的完整标题匹配获取句柄根据窗口的类别匹配获取句

在 Spring Boot 中实现异常处理最佳实践

《在SpringBoot中实现异常处理最佳实践》本文介绍如何在SpringBoot中实现异常处理,涵盖核心概念、实现方法、与先前查询的集成、性能分析、常见问题和最佳实践,感兴趣的朋友一起看看吧... 目录一、Spring Boot 异常处理的背景与核心概念1.1 为什么需要异常处理?1.2 Spring B

Python位移操作和位运算的实现示例

《Python位移操作和位运算的实现示例》本文主要介绍了Python位移操作和位运算的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 位移操作1.1 左移操作 (<<)1.2 右移操作 (>>)注意事项:2. 位运算2.1

如何在 Spring Boot 中实现 FreeMarker 模板

《如何在SpringBoot中实现FreeMarker模板》FreeMarker是一种功能强大、轻量级的模板引擎,用于在Java应用中生成动态文本输出(如HTML、XML、邮件内容等),本文... 目录什么是 FreeMarker 模板?在 Spring Boot 中实现 FreeMarker 模板1. 环

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

SpringMVC 通过ajax 前后端数据交互的实现方法

《SpringMVC通过ajax前后端数据交互的实现方法》:本文主要介绍SpringMVC通过ajax前后端数据交互的实现方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价... 在前端的开发过程中,经常在html页面通过AJAX进行前后端数据的交互,SpringMVC的controll

Spring Security自定义身份认证的实现方法

《SpringSecurity自定义身份认证的实现方法》:本文主要介绍SpringSecurity自定义身份认证的实现方法,下面对SpringSecurity的这三种自定义身份认证进行详细讲解,... 目录1.内存身份认证(1)创建配置类(2)验证内存身份认证2.JDBC身份认证(1)数据准备 (2)配置依

利用python实现对excel文件进行加密

《利用python实现对excel文件进行加密》由于文件内容的私密性,需要对Excel文件进行加密,保护文件以免给第三方看到,本文将以Python语言为例,和大家讲讲如何对Excel文件进行加密,感兴... 目录前言方法一:使用pywin32库(仅限Windows)方法二:使用msoffcrypto-too