文本超过指定行数折叠
本文发布于我的个人网站:https://wintc.top/article/58,转载请注明。
多行文本超过指定行数隐藏超出部分并显示“...查看全部”是一个常遇到的需求,网上也有人实现过类似的功能,不过还是想自己写写看,于是就写了一个Vue的组件,本文简单介绍一下实现思路。
组件可以通过npm安装使用,需要的同学可以尝试一下:
组件地址:https://github.com/Lushenggang/vue-overflow-ellipsis
在线体验:https://wintc.top/laboratory/#/ellipsis
一、需求描述
长度不定的一段文字,最多显示n行(比如3行),不超过n行正常显示;超过n行则在最后一行尾部显示“展开”或“查看全部”之类的按钮,点击按钮则展开显示全部内容,或者跳转到其它页面展示所有内容。
预期效果如下:
二、实现原理
纯CSS很难完美实现这个功能,所以还得借助JS来实现,实现思路大体相似,都是判断内容是否超过指定行数,超过则截取字符串的前x个字符,然后然后和“...查看全部”拼接在一起,这里的x即截取长度,需要动态计算。
想通过上述方案实现,有几个问题需要解决:
- 怎样判断文字是否超过指定行数
- 如何计算字符串截取长度
- 动态响应,包括响应页面布局变动、字符串变化、指定行数变化等
下面具体研究一下这些问题。
1. 怎样判断一段文字是否超过指定行数?
首先解决一个小问题:如何计算指定行数的高度?我首先想到的是使用textarea的rows属性,指定行数,然后计算textarea撑起的高度。另一个方法是将行高的计算值与行数相乘,即得到指定行数的高度,这个办法我没尝试过,但是想必可行。
解决了指定行数高度的问题,计算一段文字是否超过指定行数就很容易了。我们可以将指定行数的textarea使用绝对定位absolute脱离文档流,放到文字的下方,然后通过文本容器的底部与textarea的底部相比较,如果文本容器的底部更靠下,说明超过指定行数。这个判断可以通过getBoundingClientRect接口获取到两个容器的位置、大小信息,然后比较位置信息中的bottom属性即可。
可以这样设计DOM结构:
<div class="ellipsis-container"><div class="textarea-container"><textarea rows="3" readonly tabindex="-1"></textarea></div>{{ showContent }} <-- showContent表示字符串截取部分 --> ... 查看更多</div>
然后使用CSS控制textarea,使其脱离文档流并且不能被看到以及被触发鼠标事件等(textarea标签中的readonly以及tabIndex属性是必要的):
.ellipsis-containertext-align leftposition relativeline-height 1.5padding 0 !important.textarea-containerposition absoluteleft 0right 0pointer-events noneopacity 0z-index -1textareavertical-align middlepadding 0resize noneoverflow hiddenfont-size inheritline-height inheritoutline noneborder none
2.如何计算字符串截取长度x——双边逼近法(二分思想)
只要可以判断一段文字是否超过指定行数,那我们就可以动态地尝试截取字符串,直到找到合适的截断长度x。这个长度满足从x的位置截断字符串,前半部分+“...查看全部”等文字刚好不会超出指定行数N,但是多截取一个字,则会超出N行。最直观的想法就是直接遍历,让x从0开始增长到显示文本总长度,对于每个x值,都计算一次文字是否超过N行,没超过则加继续遍历,超过则获得了合适的长度x - 1,跳出循环。当然也可以让x从文本总长度递减遍历。
不过这里最大的问题在于浏览器的回流和重绘。因为我们每次截取字符串都需要浏览器重新渲染出来才能得到是否超过N行,这过程中就触发了浏览器的重绘或回流,每次循环都会触发一次。而对于正常的需求来说,假设N取值是3,那很可能每次计算会导致50次以上的重绘或回流,这中间消耗的性能还是非常大的,不小心可能就是几十毫秒甚至上百毫秒。这个计算过程应该在一个任务(即常说的”宏任务“)中完成,否则计算过程中会出现显示闪动的”异常“情况,所以可以说计算过程是阻塞的,因此计算的总时间一定要控制到非常低,即要减少计算的次数。
可以考虑使用"双边逼近法"(或称”二分法“)查找合适的截取长度x,大大减少尝试的次数。第一次先以文本长度为截取长度,计算是否超过N行,没超过则停止计算;超过则取1/2长度进行截取,如果此时没超过N行,则在1/2长度到文本长度之间继续二分查找,如果超过则在0到1/2文本长度中继续二分查找。直到查找区间开始值与结束值相差为1,则开始值即为所求。具体实现可以看下文中的完整代码。
3.监听页面变动
对于Vue项目来说,传入组件的字符串、行数等可能随时改变,可以watch这些属性变化,然后重新计算一次截取长度。另一方面,对于页面布局而言,可能会因为其它页面元素的增删或者样式改变,导致页面布局变动,影响到文本容器的宽度,此时也应该重新计算一次截取长度。
监听文本容器宽度的变化,可以考虑使用ResizeObserver来监听,但是这个接口的兼容性不够好(IE各个版本都不支持),因此选择了一个npm库element-resize-detector来监测(非常好用
文本超过指定行数折叠相关推荐
- 文本超过指定行数显示折叠、展开按钮并以三个点结束
需求 一段从接口获取到的文本,要求显示时,如果长度超过指定行数,则以三个点省略后面内容,并出现"全文"按钮,点击后显示全文,"全文"按钮变成"收起&q ...
- html5文本超过指定行数隐藏显示省略号
这个很简单,直接贴代码就好了 HTML <span class="name">博客园是一个面向开发者的知识分享社区.自创建以来,博客园一直致力并专注于为开发者打造一个纯 ...
- css3实现超出文本指定行数(指定文本长度)用省略号代替
测试代码: 1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta name="viewport" c ...
- 如何用python读取文本中指定行的内容
如何用python读取文本中指定行的内容 搜索资料 我来答 分享 新浪微博 QQ空间 浏览 5284 次 查看全文 http://www.taodudu.cc/news/show-64036.ht ...
- php如何打出的正方形行列,javascript实现输出指定行数正方形图案的方法
本文实例讲述了javascript实现输出指定行数正方形图案的方法.分享给大家供大家参考.具体如下: javascript实现输出指定行数的正方形图案:点击生成图案,会有2个提示框,1,输入图案的组成 ...
- php循环图案正方形,javascript输出指定行数正方形图案效果的实现方法
本文实例讲述了javascript实现输出指定行数正方形图案的方法.分享给大家供大家参考.具体如下: javascript实现输出指定行数的正方形图案:点击生成图案,会有2个提示框,1,输入图案的组成 ...
- 【C/C++】等分或指定行数把txt文档拆分成多份
1.输入如下: 2.执行代码: 3.输出如下: 4.代码如下: 4.1.平均拆分代码 #include <iostream> #include <string> #inclu ...
- VC编辑框(EDIT)的自动换行、自动滚屏 、到指定行数自动清空
From: http://getyoureyes.blog.163.com/blog/static/101716622201083081914305/ 经过多次测试,总结出VC编辑框(EDIT)的自动 ...
- Linux 查看文件指定行数 内容
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 1.tail date.log 输出文件末尾的内容,默认10行 tail ...
- eclipse查找指定行数
ctrl+L 查找指定行数 转载于:https://www.cnblogs.com/songyunxinQQ529616136/p/6640734.html
最新文章
- 小心!你的脸正在成为色情片主角……
- php linux下保存文件路径怎么写,linux下php导入带图片的word文档转为html,图片保存下来生成路径。...
- Project Student:维护Webapp(只读)
- 什么是Reconciliation?
- php+彩票中奖判断,彩票算法 – PHP – 数学似乎不错,但功能是否有效?
- 大数元科技牵手中央财经大学 助力财税金融体制改革
- jupyter notebook如何导入excel数据
- 初识SpringCache
- 双向可控硅详细用法说明
- iphone12android在线,【苹果iPhone12评测】安卓机吃尽高刷红利,为何iPhone 12还是缺席?(全文)_苹果 iPhone 12_手机评测-中关村在线...
- Shell和Jenkins讲解
- ArcPY实现分图斑批量制图
- 三层交换机配置多网段互访并上网:型号:交换机TPLINK(TL-SG5428) 路由器TPLINK(TL-WVR600G)
- 芬兰本土公司Jolla计划复兴诺基亚MeeGo系统
- 个人微信api接口调用-微信群管理
- Linux下区分物理CPU、逻辑CPU和CPU核数 1
- 下载googleplay应用
- 2.序贯最小二乘估计(仅包含滤波)
- Linux $ROOT 用户无权限操作文件/目录问题
- 计算机软件研究生,计算机软件研究生论文.docx