js控制文字溢出显示省略号
.text{display: -webkit-box;overflow: hidden;white-space: normal;text-overflow: ellipsis;word-wrap: break-word;-webkit-line-clamp: 2;-webkit-box-orient: vertical;
}
本人有个需求就是在一个盒子内有一段文本,然后控制文本显示两行,第二行要显示省略号,本人通过以上方式通过
css
解决了
但是有个问题,因为这个区域要被截图保存下来,本人使用html-to-image
插件去完成了截图操作,但就在这时,bug出现了,例如在真机上面显示省略号,但是在截图上面并没有省略号,而是完整的显示出了两行文字,可能由于这个文字大小在当前机型上面刚好溢出,但是没有达到截图的容器的溢出条件,就出现了一个尴尬的事情,截图没省略号,真机有,然后如果多补充点文字,截图虽然显示了省略号,但是省略号前面还是比真机多几个字,,,因此后面不考虑使用css来做了,改成js来做,具体步骤如下:
方式
下面提供了两种方式实现这个,主要是使用js可以解决很多问题,使用jQuery版本就不行,例如遇到uniapp这种标签皆为组件的就不行了,根本设置不了,因此像uniapp这种建议使用原生js判断
依赖于jQuery
- 方式一(静态内容非常推荐)
- 好处
- 适用于内容固定的情况,直接在页面写死换行的就行
- 坏处
- 依赖于
jquery
和jQuery.ellipsis
两个插件,需要引入一下 - 不适用于内容动态变化情况
- 依赖于
- 好处
- 方式二(动态内容非常推荐)
- 好处
- 适用于页面内容动态变换的情况
- 坏处
- 依赖于
jquery
和jQuery.ellipsis
两个插件,需要引入一下 - 需要几行就要判断几行文字
- 依赖于
- 好处
直接使用原生js
处理
- 方式一(动态内容比较推荐)
- 好处
- 适用于页面内容动态变换的情况
- 不依赖于
jquery
和jQuery.ellipsis
两个插件
- 坏处
- 行数较多的情况,需要一个一个判断
- 除了上述
jquery
方式二的(需要几行就要判断几行文字)以外,还要判断是否满行显示省略号等(不想判断可以使用jquery
的方式二,这个内部已经判断好了)
- 好处
- 方式二(静态内容比较推荐)
- 好处
- 适用于内容固定的情况,直接写死就行
- 不依赖于
jquery
和jQuery.ellipsis
两个插件
- 坏处
- 行数较多的情况,需要一个一个判断
- 好处
依赖于jQuery
使用jQuery
和jQuery.ellipsis.js
来解决
jQuery
的代码各位可以百度,这里提供一个CDN地址: https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js
jQuery.ellipsis.js
代码如下:
/*!* jQuery.ellipsis* https://github.com/jjenzz/jquery.ellipsis* --------------------------------------------------------------------------* Copyright (c) 2013 J. Smith (@jjenzz)* Dual licensed under the MIT and GPL licenses:* https://www.opensource.org/licenses/mit-license.php* http://www.gnu.org/licenses/gpl.html** adds a class to the last 'allowed' line of text so you can apply* text-overflow: ellipsis;*/
(function (a) { if (typeof define === "function" && define.amd) { define(["jquery"], a) } else { a(jQuery) } }(function (d) { var c = "ellipsis", b = '<span style="white-space: nowrap;">', e = { lines: "auto", ellipClass: "ellip", responsive: false }; function a(h, q) { var m = this, w = 0, g = [], k, p, i, f, j, n, s; m.$cont = d(h); m.opts = d.extend({}, e, q); function o() { m.text = m.$cont.text(); m.opts.ellipLineClass = m.opts.ellipClass + "-line"; m.$el = d('<span class="' + m.opts.ellipClass + '" />'); m.$el.text(m.text); m.$cont.empty().append(m.$el); t() } function t() { if (typeof m.opts.lines === "number" && m.opts.lines < 2) { m.$el.addClass(m.opts.ellipLineClass); return } n = m.$cont.height(); if (m.opts.lines === "auto" && m.$el.prop("scrollHeight") <= n) { return } if (!k) { return } s = d.trim(m.text).split(/\s+/); m.$el.html(b + s.join("</span> " + b) + "</span>"); m.$el.find("span").each(k); if (p != null) { u(p) } } function u(x) { s[x] = '<span class="' + m.opts.ellipLineClass + '">' + s[x]; s.push("</span>"); m.$el.html(s.join(" ")) } if (m.opts.lines === "auto") { var r = function (y, A) { var x = d(A), z = x.position().top; j = j || x.height(); if (z === f) { g[w].push(x) } else { f = z; w += 1; g[w] = [x] } if (z + j > n) { p = y - g[w - 1].length; return false } }; k = r } if (typeof m.opts.lines === "number" && m.opts.lines > 1) { var l = function (y, A) { var x = d(A), z = x.position().top; if (z !== f) { f = z; w += 1 } if (w === m.opts.lines) { p = y; return false } }; k = l } if (m.opts.responsive) { var v = function () { g = []; w = 0; f = null; p = null; m.$el.html(m.text); clearTimeout(i); i = setTimeout(t, 100) }; d(window).on("resize." + c, v) } o() } d.fn[c] = function (f) { return this.each(function () { try { d(this).data(c, (new a(this, f))) } catch (g) { if (window.console) { console.error(c + ": " + g) } } }) } }));
引入到页面使用
方式一(固定内容推荐,非动态内容不推荐)
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script><script src="./jQuery.ellipsis.js"></script><style>.aaa,.aaa2 {background: #eee;border: 1px solid #ccc;width: 130px;margin-left: 200px;}.aaa2{margin-top: 50px;}/* 下面这三个css不能删,否则不起作用了 */.ellip {display: block;height: 100%;}.ellip-line {display: inline-block;text-overflow: ellipsis;white-space: nowrap;word-wrap: normal;}.ellip,.ellip-line {position: relative;overflow: hidden;max-width: 100%;}</style>
</head><body><div class="aaa">你哈哈哈哈哈哈啊哈哈哈哈哈哈哈颇大开发跑我就发很日入好闺女诶欧哈你噶IEUR个</div><div class="aaa2">你哈哈哈哈哈哈啊 哈哈哈哈哈哈哈颇大开发跑我就发很日入好闺女诶欧哈你噶IEUR个</div><script>$('.aaa').ellipsis({ lines: 2 }); // 控制第二行溢出显示省略号$('.aaa2').ellipsis({ lines: 2 }); // // 控制第二行溢出显示省略号</script>
</body></html>
上面内容可以看到,需要换行的部分必须手动在html里面加换行或者
,因此这种方式适合静态的,不适用于动态的,可以看下面这个
方式二(动态内容推荐)
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script><script src="./jQuery.ellipsis.js"></script><style>.aaa {background: #eee;border: 1px solid #ccc;width: 150px;}/* 下面这三个css不能删,否则不起作用了 */.ellip {display: block;height: 100%;}.ellip-line {display: inline-block;text-overflow: ellipsis;white-space: nowrap;word-wrap: normal;}.ellip,.ellip-line {position: relative;overflow: hidden;max-width: 100%;}</style>
</head><body><div class="aaa">abababababa我还得覅维护诶哈哈哈哈哈哈颇大开发跑我就发很日入好闺女诶欧哈你噶IEUR个</div><script>function getTextWidth(text, font) {// 计算字符串的宽// 创建临时canvas元素var canvas = document.createElement("canvas");var context = canvas.getContext("2d");context.font = font;return context.measureText(text).width;}let aaa = document.querySelector('.aaa'); // 获取容器let aaawidth = aaa.clientWidth; // 拿到容器的宽度let text = aaa.innerText;let font = getComputedStyle(aaa).font; // 获取元素的实际字体样式(为了算文字大小,这个跟字符串的宽有影响,如果容器上面加了字体,这里同样会返回这个字体,可以打印font查看,也就是说,这个方法兼容带字体的情况)let textWidth = getTextWidth(text, font); // 计算字符串的宽度console.log(aaawidth,textWidth); // 容器的宽和字符串的宽度let textarr = text.split('') // 将字符串分割成数组进行遍历let start_str = '' // 第一行的文字内容let end_str = '' // 第二行的文字内容(还可以加其他更多的行,只需要在下面多几个判断就好)let linshistr = '' // 临时存储用于计算的字符串textarr.forEach((item)=>{linshistr += item // 每次循环都让临时字符串累加// 下面如果有第二行第三行的话直接判断 > n*aaawidth 即可if(getTextWidth(linshistr, font) > aaawidth){// 如果小于容器容器宽度,让第一行的字符串进行累加end_str += item }else{// 如果超出容器,都是在第二行,直接让第二行元素累加start_str+= item}})console.log(start_str, end_str); // 获取第一行和第二行元素内容aaa.innerHTML = start_str + ' ' + end_str // 加个 可以换行,就像方式一写死的一样$('.aaa').ellipsis({ lines: 2 }); // 再去使用jQuery.ellipsis.js的ellipsis方法让第二行显示省略号</script>
</body></html>
直接使用js
方式一(动态内容推荐)
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.aaa {background: #eee;border: 1px solid #ccc;width: 154px;}</style>
</head><body><div class="aaa"><div class="son"></div><div class="son2"></div></div><script>// let str = 'a我还得覅维护诶好啊' // 获取文本内容(一行满的情况)// let str = 'a我还得覅维护诶' // 获取文本内容(一行不满的情况)// let str = 'a我还得覅维护诶哈哈哈哈i和ID号次我深有感触' // 获取文本内容(两行满的情况)// let str = 'a我还得覅维护诶哈哈哈你好啊我爱你' // 获取文本内容(两行不满的情况)function getTextWidth(text, font) {// 计算文本字符串的宽// 创建临时canvas元素var canvas = document.createElement("canvas");var context = canvas.getContext("2d");context.font = font;return context.measureText(text).width;}// 获取元素实际的容器let aaa = document.querySelector('.aaa');let aaawidth = aaa.clientWidth; // 获取容器宽度let font = getComputedStyle(aaa).font; // 获取元素的实际字体样式,(为了算文字大小,这个跟字符串的宽有影响,会返回字体的大小和字体名称,如果是固定的话也可以直接写死,这个是从容器上面获取的字体大小和字体名称)let textWidth = getTextWidth(str, font); // // 计算字符串的宽度console.log(aaawidth, textWidth); // // 容器的宽和字符串的宽度let textarr = str.split('') // 将字符串分割成数组进行遍历let start_str = '' // 第一行的文字内容let end_str = '' // 第二行的文字内容(还可以加其他更多的行,只需要在下面多几个判断就好)let linshistr = '' // 临时存储用于计算的字符串textarr.forEach((item) => {linshistr += item// 第一行的判断if (getTextWidth(linshistr, font) < aaawidth) {start_str += item}// 第二行的判断if (getTextWidth(linshistr, font) > aaawidth && getTextWidth(linshistr, font) < 2 * aaawidth) {end_str += item}// 第n行的判断// if (getTextWidth(linshistr, font) > ( n - 1 ) * aaawidth &&getTextWidth(linshistr, font) > n * aaawidth) {}})console.log(start_str, end_str); // 输出第一行和第二行的文字内容// 如果第二行不存在,就只显示一行// 这里需要判断是否占满容器(这里我判断容器宽度减去10像素如果小于文字宽度大小就加省略号,否则原样输出,这里的10大家可以根据项目自行改)if (end_str == '') {document.querySelector('.son').innerHTML = aaawidth - 10 < getTextWidth(start_str, font) ? start_str.substring(0, start_str.length - 1) + '...' : start_str;} else {// 第二行存在,则第一行肯定会存在document.querySelector('.son').innerHTML = start_strdocument.querySelector('.son2').innerHTML = aaawidth - 10 < getTextWidth(end_str, font) ? end_str.substring(0, end_str.length - 1) + '...' : end_str;}</script>
</body></html>
方式二(固定内容推荐,非动态内容不推荐)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.aaa {background: #eee;border: 1px solid #ccc;width: 154px;}</style>
</head>
<body><div class="aaa"><div class="son"></div><div class="son2"></div></div><script>let aaa = document.querySelector('.aaa');let son = document.querySelector('.son');let son2 = document.querySelector('.son2');let str = 'a我还得覅维护诶ha'// 这种方式比较暴力,直接截取字符串(适用于静态内容)if (str.length < 10) {son.innerHTML = str.substring(0, 10)}else if(str.length == 10){son.innerHTML = str.substring(0, 10)+'...'}else if(str.length > 10&&str.length < 20){son.innerHTML = str.substring(0, 10)son2.innerHTML = str.substring(10,20)}else if(str.length >= 20){son.innerHTML = str.substring(0, 10)son2.innerHTML = str.substring(10,20)+'...'}</script>
</body>
</html>