前端学堂
学有所用

多行超出尾部展示省略号(改进)


前言

之前写过一个多行自动显示省略号的文章,网上也能查到很多资料。超出两行展示省略号, 这两天抽时间做了一个退化处理,就是支持-webkit-box属性的浏览器中采用css来控制,不支持这一属性的浏览器如IE9以上、火狐浏览器,则使用JS动态计算的方法裁剪文本,在文本末未追加省略号(…)。在这个过程中,出乎意外的发现了chrome浏览器的一个bug,版本 55.0.2883.87 m.

多行超出尾部展示省略号(改进)

展示bug

你可以试试下面的代码,在hover的时候,尾部的省略号…不会跟着变色。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
div{
color: blue;
}
span{
overflow:hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
width: 100px;
color: blue;
font-family: 微软雅黑, "Microsoft YaHei";
}
span:hover{
color: red;
}
</style>
</head>
<body>
<div>
<a href="www.baidu.com"><span>测试测试测试试1测试111试</span></a>
</div>
</body>
</html>

是不是很神奇,这是chrome 浏览器的一个bug。居然能找到浏览器的bug,真是很开心。
这个bug的复现条件是文本内容不能多,不能少,刚好在显示省略号的边界。最好的衡量方法是更换字体时用粗体会出现省略号,用宋体则不会展示省略号,那么就可以复现了。

解决方案

已经像chrome反馈了这个问题,等待更新。

说说我的退化方案吧

需要处理的难题是如何判断文本超出设定的显示范围,比如设定展示2行,那么怎么判断超出了两行呢?
需要知道一个两个dom函数:getComputedStyle 和currentStyle。这两个函数都是获取dom节点渲染后计算出来的属性,也就对应于computed attribute.
其中:getComputedStyle兼容IE9+,火狐和chrome,currentStyle适用于ie8及以下
处理的方法就是判断节点的渲染后的高度是不是超出了行高乘以行数,超出了则是需要裁剪字数。裁剪字数采用了一个近似方程:
裁剪后的字数 = 当前字数 展示的行数 行高 / 渲染后展示的高度
ps: 注意有个坑,就是currentStyle拿到的高度始终是auto,而在ie9可以通过拿父元素的高度的方式拿到

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
if (!document.getElementsByClassName) {
document.getElementsByClassName = function (className, element) {
var children = (element || document).getElementsByTagName('*');
var elements = new Array();
for (var i = 0; i < children.length; i++) {
var child = children[i];
var classNames = child.className.split(' ');
for (var j = 0; j < classNames.length; j++) {
if (classNames[j] == className) {
elements.push(child);
break;
}
}
}
return elements;
};
}
//获取元素计算后展示的style
function getStyle(obj, attr) {
return getComputedStyle(obj) ? getComputedStyle(obj)[attr] : obj.currentStyle[attr];
}
var _tempLineH = 0;
var _tempHeight = 0;
for (var j = 2; j < 5; j++) {
var _cateNavBoxList = document.getElementsByClassName('f-' + j + 'lines');
if (!_cateNavBoxList.length) continue;
for (var i = 0; i < _cateNavBoxList.length; i++) {
var item = _cateNavBoxList[i];
_tempLineH = parseInt(getStyle(item, "lineHeight"));
if (getStyle(item, "height") == "auto") {
item.parentElement.style.height = "auto";
_tempHeight = parseInt(getStyle(item.parentElement, "height"));
} else {
_tempHeight = parseInt(getStyle(item, "height"));
}
if (_tempHeight > j * _tempLineH) {
item.innerText = item.innerText.substr(0, item.innerText.length * j * _tempLineH / _tempHeight - 1) + "...";
}
}
}

改进篇

由于上面的方法在截取字数的时候,算法比较粗糙,只是简单地计算比例关系。这里做了改进。上面算法最好的情况的是正好字数刚刚满;最差的情况是最后一行只能显示寥寥无几的几个文字加上…,这显然是不是我们的追求,于是乎可以改进一下。其实改进很简单,在上面算法的基础上,计算出来裁剪字数之后不断增加字数,当渲染后的高度刚好超过需要的行数的高度时候,这时的字数就是需要截取的准确字数。
代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
//解决IE8之类不支持getElementsByClassName
if (!document.getElementsByClassName) {
document.getElementsByClassName = function (className, element) {
var children = (element || document).getElementsByTagName('*');
var elements = new Array();
for (var i = 0; i < children.length; i++) {
var child = children[i];
var classNames = child.className.split(' ');
for (var j = 0; j < classNames.length; j++) {
if (classNames[j] == className) {
elements.push(child);
break;
}
}
}
return elements;
};
}
//获取元素计算后展示的style
function getStyle(obj, attr) {
return getComputedStyle(obj) ? getComputedStyle(obj)[attr] : obj.currentStyle[attr];
}
//获取元素计算后展示的高度
function getHeight(item) {
if (getStyle(item, "height") == "auto") {
item.parentElement.style.height = "auto";
return parseInt(getStyle(item.parentElement, "height"));
} else {
return parseInt(getStyle(item, "height"));
}
}
var _tempLineH = 0;
var _tempHeight = 0;
for (var j = 2; j < 5; j++) {
var _cateNavBoxList = document.getElementsByClassName(('f-' + j + 'lines'), document.body);
if (!_cateNavBoxList.length) continue;
for (var i = 0; i < _cateNavBoxList.length; i++) {
var item = _cateNavBoxList[i];
_tempLineH = parseInt(getStyle(item, "lineHeight"));
_tempHeight = getHeight(item);
if (_tempHeight > j * _tempLineH) {
var leng = item.innerText.length * j * _tempLineH / _tempHeight - 1;
var _tempText = item.innerText;
item.innerText = _tempText.substr(0, leng);
_tempHeight = getHeight(item);
var k=0;
while (_tempHeight <= j * _tempLineH) {
k++;
item.innerText = _tempText.substr(0, leng + k);
_tempHeight = getHeight(item);
}
item.innerText = _tempText.substr(0, item.innerText.length - 3)+"...";
}
}
}

谢谢!

转载请注明出处://fed123.oss-ap-southeast-2.aliyuncs.com/2017/01/20/2017_chromeBug/
欢迎关注皓眸学问公众号(扫描左侧二维码),每天好文、新技术!任何学习疑问或者工作问题都可以给我留言、互动。T_T 皓眸大前端开发学习 T_T

赞(0) 打赏
未经允许不得转载:前端学堂 » 多行超出尾部展示省略号(改进)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏