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;
};

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/24368.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在MySQL中实现upsert:如果不存在则插入?

目录 1 使用 REPLACE 2 使用 INSERT ... ON DUPLICATE KEY UPDATE 使用 INSERT IGNORE 有效会导致 MySQL 在尝试执行语句时忽略执行错误 INSERT 。这意味着 包含 索引或 字段 INSERT IGNORE 中重复值的语句 不会 产生错误&#xff0c;而只是完全忽略该特定 命令。其明显目的是…

[word] word大括号怎么打两行 #其他#其他#微信

word大括号怎么打两行 Word给用户提供了用于创建专业而优雅的文档工具&#xff0c;帮助用户节省时间&#xff0c;并得到优雅美观的结果。 一直以来&#xff0c;Microsoft Office Word 都是最流行的文字处理程序。 作为 Office 套件的核心程序&#xff0c; Word 提供了许多易…

秒杀优化+秒杀安全

1.Redis预减库存 1.OrderServiceImpl.java 问题分析 2.具体实现 SeckillController.java 1.实现InitializingBean接口的afterPropertiesSet方法&#xff0c;在bean初始化之后将库存信息加载到Redis /*** 系统初始化&#xff0c;将秒杀商品库存加载到redis中** throws Excepti…

【YOLOv10】使用 TensorRT C++ API 调用GPU加速部署 YOLOv10 实现 500FPS 推理速度——快到飞起!

NVIDIA TensorRT ™ 是一款用于高性能深度学习推理的 SDK&#xff0c;包含深度学习推理优化器和运行时&#xff0c;可为推理应用程序提供低延迟和高吞吐量。YOLOv10是清华大学研究人员近期提出的一种实时目标检测方法&#xff0c;通过消除NMS、优化模型架构和引入创新模块等策…

平稳交付 20+ 医院,卓健科技基于 OpenCloudOS 的落地实践

导语&#xff1a;随着数字化转型于各个行业领域当中持续地深入推进&#xff0c;充当底层支撑的操作系统正发挥着愈发关键且重要的作用。卓健科技把 OpenCloudOS 当作首要的交付系统&#xff0c;达成了项目交付速度的提升、安全可靠性的增强、运维成本的降低。本文将会阐述卓健科…

【转】ES, 广告索引

思考&#xff1a; 1&#xff09;直接把别名切换到上一个版本索引 --解决问题 2&#xff09;广告层级索引如何解决&#xff1f; -routing、join 3&#xff09;查询的过程&#xff1a;query and fetch, 优化掉fetch 4&#xff09;segment合并策略 5&#xff09;全量写入时副…

gcc与g++的原理

程序的翻译 1 快速认识gcc/g2 程序翻译的过程2.1 预处理阶段2.2 编译阶段2.3 汇编阶段2.4 链接阶段 3 动静态库 1 快速认识gcc/g 首先我们需要在linux系统中安装对应的编译器gcc/g&#xff0c;安装命令如下&#xff08;centos7环境下&#xff09;&#xff1a; gcc: yum instal…

什么是哈希冲突?如何解决哈希冲突?HashMap和TreeMap之间的区别?

Map 和 Set 的概念 Map和Set是一种专门用来进行搜索的容器或者数据结构&#xff0c;其搜索的效率与其具体的实例化子类有关 。 为什么说它是一种专门用来进行搜索的数据结构呢&#xff1f; 我们应该都用过“遍历查找”、“二分查找”&#xff0c;这两种方式也都是用来对目标…

Spring Security系列之PasswordEncoder

概述 任何一个登录系统的密码不能明文存储&#xff0c;万一发生数据库泄漏事故&#xff08;不管是内部人员导出数据库数据还是被黑客攻击破解数据库实例节点拿到数据库数据等&#xff0c;又或者是其他情况造成的&#xff09;&#xff0c;将产生巨大的损失。因此明文密码在存储…

DOS 操作系统

DOS 介绍 DOS&#xff1a;disk operating system&#xff0c;磁盘操作系统。 中国DOS联盟下载 MS-DOS 7.10完整安装版&#xff08;含图形安装程序&#xff09; DOS 环境下的操作 输入部分内容后按下 Tab 可以快速自动补全。 按住 Ctrl 键可以用鼠标滚轮改变字号大小。 DO…

【数据结构初阶】--- 顺序表

顺序表&#xff0c;好像学C语言时从来没听过&#xff0c;实际上就是给数组穿了层衣服&#xff0c;本质是一模一样的。 这里的顺序表实际是定义了一个结构体&#xff0c;设计各种函数来实现它的功能&#xff0c;比如说数组中的增删改查插入&#xff0c;这些基本操作其实平时就会…

c++调用动态库LNK2019无法解析的外部符号LNK1120无法解析的外部命令

严重性 代码 说明 项目 文件 行 禁止显示状态 错误 LNK1120 6 个无法解析的外部命令 ConsoleApplication1 D:\vs_qt_project\ConsoleApplication1\x64\Debug\ConsoleApplication1.exe 1 严重性 代码 说明 项目 文件 行 …

应用层——HTTP协议(自己实现一个http协议)——客户端(浏览器)的请求做反序列化和请求分析,然后创建http向响应结构

应用层&#xff1a;之前我们写的创建套接字&#xff0c;发送数据&#xff0c;序列化反序列化这些都是在写应用层 我们程序员写的一个个解决我们实际问题, 满足我们日常需求的网络程序, 都是在应用层 之前的网络计算机是我们自定义的协议&#xff1a;传输的数据最终是什么样的结…

高级文件操作

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 Python内置的os模块除了可以对目录进行操作&#xff0c;还可以对文件进行一些高级操作&#xff0c;具体函数如表4所示。 表4 os模块提供的与文件相…

【AI基础】第三步:纯天然保姆喂饭级-安装并运行chatglm2-6b

chatglm2构建时使用了RUST&#xff0c;所以在安装chatglm2之前&#xff0c;先安装RUST。 此系列文章列表&#xff1a; 【AI基础】第一步&#xff1a;安装python开发环境-windows篇_下载安装ai环境python-CSDN博客 【AI基础】第一步&#xff1a;安装python开发环境-conda篇_mini…

知识图谱的应用---智慧司法

文章目录 智慧司法典型应用 智慧司法 智慧司法是综合运用人工智能、大数据、互联网、物联网、云计算等信息技术手段&#xff0c;遵循司法公开、公平、公正的原则&#xff0c;与司法领域业务知识经验深度融合&#xff0c;使司法机关在审判、检查、侦查、监管职能各方面得到全面的…

【数据结构】图论入门

引入 数据的逻辑结构&#xff1a; 集合&#xff1a;数据元素间除“同属于一个集合”外&#xff0c;无其他关系线性结构&#xff1a;一个对多个&#xff0c;例如&#xff1a;线性表、栈、队列树形结构&#xff1a;一个对多个&#xff0c;例如&#xff1a;树图形结构&#xff1…

SpringBoot中的WebMvcConfigurationSupport和WebMvcConfigurer

在SpringBoot中可以通过以下两种方式来完成自定义WebMvc的配置&#xff1a; &#xff08;1&#xff09;继承WebMvcConfigurationSupport类 &#xff08;2&#xff09;实现WebMvcConfigurer接口 通过这两种方式完成的WebMvc配置存在差异&#xff0c;本文将对此作简单说明与区…

【Vue】单页应用程序介绍

通常基于Vue去开发一整个网站&#xff0c;开发出来的这整个网站应用&#xff0c;我们都会叫做单页应用程序 概念 单页应用程序&#xff1a;SPA【Single Page Application】是指所有的功能都在一个html页面上实现 我们可以将页面共用的部分封装成组件&#xff0c;底下要切换的也…

工具-金舟投屏软件: 手机如何投屏到电脑上 / Wi-Fi / USB

金舟安卓/iOS苹果投屏-正版软件下载中心 方法一、金舟投屏软件-wifi 1.1、准备工作 确保苹果手机和Windows电脑都连接到同一个Wi-Fi网络。 在Windows电脑上安装并打开金舟投屏软件。 1.2、操作步骤 在金舟投屏软件上选择“苹果手机投屏”功能。 在苹果手机上下滑屏幕&am…