介绍一下之前做过的一个需求,是要实现pc的一个聊天软件的消息引用功能。对于文件的引用,产品是这样做要求的:
- 消息框无固定长度,根据回复的文字长度决定消息框长度
- 对于一个pc项目,当页面窗口变化时要实现响应式
- 文件名过长的情况下,不能简单的省略文字,需要省略中间部分文字保留后缀名
看看效果:
页面可容下的情况:
页面不能容下的情况:
实现:
首先肯定想到的是监听页面大小变化的同时,计算文本内容长度和框的内容长度,进行比较来实现,也就是:
黄框-蓝框-红框 = 内容区域长度 与文字长度进行比较。当文字长度大于内容区域长度的时候进行隐藏。
const fileTextDetail = this.$refs.fileTextDetail
const replyContent = this.$refs.replyContent
const quoteReplyWrap = this.$refs.quoteReplyWrap
const fileIcon = this.$refs.fileIcon
const quoteReplyWrapWidth = quoteReplyWrap.offsetWidth;
const fileIconWidth = fileIcon.offsetWidth;
const replyContentWidth = replyContent.offsetWidth;
const fileTextDetailWidth = fileTextDetail.scrollWidth;
const textContentWidth = replyContentWidth - (quoteReplyWrapWidth+4) - fileIconWidth;
console.log(textContentWidth,fileTextDetailWidth,'width');
// 如果文本宽度大于容器宽度,则进行处理
// debugger;
if(fileTextDetailWidth > textContentWidth){
//todo
}
到此为止都还是一个比较简单的事情,但是怎么选择文字省略的部分?前后各保留多少个字??随着页面的任意拉大拉小,文字保留的部分也是会有变化的。
第一次交付的时候,我选择固定保留的字数,然后去说服产品~~~最最最终是被打回重做了。
第二次交付考虑使用纯css:将内容部分分为前半段和后半段,通过前半段设置text-overflow: ellipsis
后半段不动的方式。后面发现前半段省略号与后半段内容有间隔,还是被产品无情打回了。
第三次交付的时候痛定思痛,决定潜心研究js实现的方式。
思路
- 计算平均字符宽度
const avgCharWidth = fileTextDetailWidth / this.messageExtra.content.name.length;
- 基于这个平均宽度和给定的文本内容显示宽度,计算出可以完整显示的字符数量(减去用于省略号的3个字符)
const visibleChars = Math.floor(textContentWidth / avgCharWidth) - 3; // 3个字符用于省略号
- 提取开始和结束文本:
const startText = this.messageExtra.content.name.slice(0, Math.floor(visibleChars / 2));
const endText = this.messageExtra.content.name.slice(-Math.floor(visibleChars / 2));
this.fileTextContent = `${startText}...${endText}`;
到这一步就大功告成,优雅实现了效果。