实现文字展开收起效果
1,css
1.1 单行
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
1.2 多行
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
text-overflow: ellipsis;
overflow: hidden;
2, JS 方式
这种方式是效果最好的,当然也是浏览器负荷最高的一种
逻辑就是在不可见的位置创建一个和显示区一模一样的元素,
然后模拟填入内容,直到超过或者小于计算因得的高度为止
好处是纯js操作,不会出现兼容性问题
let ellipsisContainer = document.createElement('div')
ellipsisContainer.setAttribute('aria-hidden', 'true')
document.body.appendChild(ellipsisContainer)
const style = getComputedStyle(this.container) // this.container 显示区 div,getComputedStyle 获取当前元素所有最终使用的CSS属性值,只读,window 方法,可直接使用
let cstyle = getDomComputedStyle(style)
function getDomComputedStyle(style){
const styleNames = Array.prototype.slice.apply(style);
return styleNames.map(name => `${name}: ${style.getPropertyValue(name)};`).join('');
}
const lineHeight = getNumber(style.lineHeight)
function getNumber(value){
if (!value) return 0
const match = value.match(/^\d*(\.\d*)?/);
return match ? Number(match[0]) : 0;
}
const maxHeight = lineHeight * ( 3 + 1) // 这里的数值 ,主要看 计算高度的逻辑 和 需求要求几行隐藏 ,具体问题具体分析
ellipsisContainer.setAttribute('style', cstyle)
ellipsisContainer.style.position = 'fixed'
ellipsisContainer.style.left = '0'
ellipsisContainer.style.height = 'auto'
ellipsisContainer.style.minHeight = 'auto'
ellipsisContainer.style.maxHeight = 'auto'
ellipsisContainer.style.top = '-999999px'
ellipsisContainer.style.zIndex = '-1000'
ellipsisContainer.style.textOverflow = 'clip'
ellipsisContainer.style.whiteSpace = 'normal'
ellipsisContainer.style.webkitLineClamp = 'none'
ellipsisContainer.innerHTML = text
if (ellipsisContainer.offsetHeight < maxHeight) { // 如果未超过 , 直接显示
this.setState({text, ellipsis: false}) // 这里是 react 更新值得操作
document.body.removeChild(ellipsisContainer)
}else {
ellipsisContainer.innerHTML = ``
const textNode = document.createTextNode(text)
ellipsisContainer.appendChild(textNode)
const ellipsisTextNode = document.createTextNode('...')
ellipsisContainer.appendChild(ellipsisTextNode)
const fixedContentNode = document.createTextNode('...展开')
ellipsisContainer.appendChild(fixedContentNode)
let ellipsisText = <div>{measureText(textNode, text)}...<span onClick={() => {this.changeEllipsis()}} style={{color: '#00B0F0'}}>展开<Icon style={{marginBottom: '-2.6px'}} size='xs' type='down'/> </span></div>
document.body.removeChild(ellipsisContainer)
let fText = <div style={{overflow: 'hidden'}}>{text}<span onClick={() => {this.changeEllipsis()}} style={{color: '#00B0F0',float: 'right'}}>收起<Icon style={{marginBottom: '-3.1px'}} size='xs' type='up'/> </span></div>
this.setState({ellipsisText,text: fText})
}
function measureText(textNode, fullText, startLoc = 0, endLoc = fullText.length ) { // 采用二分法迭代 尽快找取适合高度的字符数量 我理解还有更好的做法,比如说 预判指定行数的字符数,由于中英文占宽不一致。所以只能预判,然后在最后加字减字,这种应该会更快
const midLoc = Math.floor((startLoc + endLoc) / 2)
const currentText = fullText.slice(0, midLoc)
textNode.textContent = currentText
if (ellipsisContainer.offsetHeight < maxHeight) {
return midLoc == endLoc - 1 ? currentText : measureText(textNode, fullText, midLoc, endLoc)
}else{
return startLoc == midLoc - 1 ? fullText.slice(0, startLoc) : measureText(textNode, fullText, startLoc, midLoc)
}
}
· [翻译] 为什么 Tracebit 用 C# 开发
· 腾讯ima接入deepseek-r1,借用别人脑子用用成真了~
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· DeepSeek崛起:程序员“饭碗”被抢,还是职业进化新起点?
· RFID实践——.NET IoT程序读取高频RFID卡/标签