那些你不知道的 getClientRects()

本文介绍了一种使用JavaScript和CSS实现前端文本自动截断并添加展开功能的方法,通过getClientRects()和getBoundingClientRect()精确控制文本显示行数,同时利用Vue.js的$nextTick确保DOM更新后的正确测量。

1.getClientRects()。是可以获取内联元素的内容有多少行

最近一个交互,在限定文字展现是5行,超过5行,则在后面添加。。。展开。如果没有展开二字,我们一般用css就能完成了。但是为了交互更人性化

text-overflow:
-o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 5;
-webkit-box-orient: vertical;

来看看代码,是如何实现的,一定要弄一个默认的span来判断行数,得到5行嗯能显示什么文字。然后记录下来

 let txtDom = this.$refs.textContainer;
            txtDom.innerHTML = originalTxt; //第一次全部渲染
            let showtxtdom = originalTxt;
            let texLength = txtDom.getClientRects();
            let h = getLength(texLength);
            let tl = 0;
            if (h <= 5) {
              obj.unfoldFlag = false;
            } else {
              obj.unfoldFlag = true;
            }
            
             while (h > 5) {
              var step = 1;
              if (/<br\/>$/.test(showtxtdom)) {
                //回退的时候,如果碰到换行要整体替换
                step = 5;
              }
              showtxtdom = showtxtdom.slice(0, -step);
              //console.log(showtxtdom);
              txtDom.innerHTML =
                showtxtdom +
                '<span>...</span><span class="comm-item-content-spread-s">展开</span>';
              // console.log(txtDom.innerHTML);
              h = getLength(txtDom.getClientRects());
              tl += step;
            }obj.showTxt = showtxtdom;
            //点赞是否是已经默认的
            obj.statedefaut = item.state;
            obj.imgsrcselect =
              "http://img.58cdn.com.cn/chinahr/img/agree_ic_sel@3x.gif?" +
              new Date().getTime();
            let regroupdata = Object.assign({}, obj, item);
            return regroupdata;
          });
          // console.log(newlist);
          //this.$set(this.commentListdata.commentList, newlist);
          this.commentListArrObj = this.commentListArrObj.concat(newlist);
          this.commentListdata = communitydetailData.data;
          this.commentListdata.commentList = this.commentListArrObj;
          // console.log(this.commentListdata);
          return;
        }

2.getBoundingClientRect() 获取盒模型,元素的高度和定位,left +top.在vue里面经常遇到

Element.getBoundingClientRect().width =  border-left-width + padding-left + width + padding-right + border-right-width

Element.getBoundingClientRect().height =  border-top-width + padding-top + height + padding-bottom + border-bottom-width

3.$nextTick 的应用/nextTick:在下次 DOM 更新循环结束之后执行延迟回调。

  • 很多时候我们需要做到,动态算content的高度,就要手动减去头部+尾部的高度。我们需要等到数据加载完成之后,在做操作
  • 方法就是监听数据的变化,然后在监听里面做搞的元算

    watch: {
         commentListdata: function() {
           this.$nextTick(() => {
             //console.log("--nextTick--");
             this.wrapperHeight = document.documentElement.clientHeight - this.$refs.wrapper.getBoundingClientRect().top;
             this.hasnowrapHeight = this.wrapperHeight - this.$refs.commmainwrap.getBoundingClientRect().height - this.$refs.commfootwrap.getBoundingClientRect().height;
           });
         }
       }
<think>我们被要求提供关于getClientRects方法的用法或解决问题,包括使用说明和常见问题。根据提供的引用,我们可以总结如下:引用[1]和[2]指出:-getClientRects()返回一个TextRectangle集合(TextRectangleList对象),每个TextRectangle对象包含top,left,bottom,right,width,height六个属性。-此方法主要针对inline元素(如a,span,em等)的文本区域。-常用于获取鼠标位置(如放大镜效果)或类似微博用户信息卡的位置。引用[3]通过代码示例说明:-getClientRects()返回一个包含一个或多个DOMRect对象的数组。常见问题和使用说明:1.**使用说明**:-语法:`letrectList=element.getClientRects();`-返回值:一个DOMRectList对象,是DOMRect对象的集合,每个DOMRect对象表示元素中每个边框的矩形(对于内联元素,可能会有多个矩形,因为内联元素可能会跨行)。-矩形属性:每个矩形有top,left,bottom,right,x,y,width,height属性(注意:x,y是较新的属性,表示矩形左上角的坐标)。-应用场景:需要获取内联元素(如多行文本)的每一行的位置信息。2.**常见问题**:-**浏览器兼容性**:引用[2]提到,除了Safari和Firefox2.0外,大多数浏览器都支持。但在现代浏览器中,支持性已经很好。注意:在IE中,对于内联元素,getClientRects()返回的范围与非IE浏览器有差异(IE返回的范围较大)。-**非内联元素**:对于块级元素,getClientRects()通常返回一个矩形(因为块级元素会跨行)。但是,如果块级元素被分割(例如,由于分页或多列布局),则可能返回多个矩形。过通常,我们只在需要处理内联元素的多行时才使用此方法。-**与getBoundingClientRect()的区别**:-getBoundingClientRect()返回一个单一的DOMRect对象,表示整个元素的边界矩形(包括所有内联子元素和边框)。-getClientRects()返回一个矩形列表,每个矩形代表元素中的一个行盒(对于内联元素)或者整个元素(对于块级元素,但通常只有一个矩形)。-**空元素调用**:根据引用[2],即使DOM里没有文本,getBoundingClientRect()也会返回一个矩形,而getClientRects()在没有内容时返回的列表长度可能为0(对于没有内容的元素)。3.**示例代码**:```javascript//获取元素的所有矩形letrects=document.getElementById('inlineElement').getClientRects();for(leti=0;i<rects.length;i++){console.log(`矩形${i+1}:top=${rects[i].top},left=${rects[i].left},width=${rects[i].width},height=${rects[i].height}`);}```4.**注意事项**:-如果元素是内联元素且跨多行,那么返回的矩形数等于行数。-矩形坐标是相对于视口的(viewport),如需相对于文档,需要加上滚动距离(window.scrollX和window.scrollY)。5.**常见使用案例**:-**文本选区定位**:当需要获取一段内联文本中每一行的位置(比如实现文本高亮效果)。-**自定义上下文菜单**:根据点击的文本行位置显示菜单。-**放大镜效果**:在鼠标悬停在文本上时,根据鼠标位置获取当前文本行的矩形信息,然后显示放大效果。6.**已知问题**:-在旧版IE中,内联元素返回的矩形可能包括整个元素的边界(而是每一行),因此需要谨慎处理。总结:getClientRects()主要用于获取内联元素的行盒(lineboxes)的位置和尺寸,而getBoundingClientRect()则用于获取整个元素的位置和尺寸。在实际应用中,如果需要单个矩形(比如定位一个块级元素)则使用getBoundingClientRect();如果需要内联元素的多行矩形信息,则使用getClientRects()。另外,根据引用[1],微博用户信息卡就是通过getClientRects()实现的,它可能是在用户的每个消息行上使用,以便在用户悬停在用户名上时,在正确的位置显示信息卡。现在,我们将根据上述总结编写回答。</think> ### `getClientRects()` 方法使用说明及常见问题 #### **基本语法** ```javascript let rectList = element.getClientRects(); ``` - **返回值**:`DOMRectList`集合(类数组),包含元素所有边框盒的坐标信息 - **每个矩形对象属性**:`top`, `left`, `bottom`, `right`, `width`, `height`, `x`, `y` #### **核心用途** 1. **内联元素多行定位**(核心场景) - 对于`display:inline`的元素(如`<span>`, `<a>`, `<em>`),当文本折行时: ```html <span id="target">两行文本的行内元素示例</span> ``` ```javascript const rects = document.getElementById('target').getClientRects(); console.log(rects.length); // 输出2(表示有两行矩形框) ``` 2. **文本区域操作** - 获取文本选区坐标(放大镜效果定位) - 自定义文本高亮位置计算 - 微博用户信息卡定位实现[^1] #### **浏览器兼容性与差异** | 浏览器 | 支持情况 | 特殊说明 | |--------------|-----------------------------------|----------------------------| | Chrome/Firefox | 完全支持 | Firefox 3.1+ 支持width/height | | Safari | 完全支持 | - | | IE9+ | 支持但范围计算较大 | 返回包含整个元素的矩形[^2] | | 移动端浏览器 | 主流支持 | 需测试特定机型 | #### **经典代码示例** ```javascript // 获取多行文本每行坐标 const textRects = document.querySelector('.multi-line-text').getClientRects(); // 在每行文本下方绘制横线 textRects.forEach(rect => { const line = document.createElement('div'); line.style.position = 'absolute'; line.style.top = `${rect.bottom}px`; line.style.left = `${rect.left}px`; line.style.width = `${rect.width}px`; line.style.height = '2px'; line.style.background = 'red'; document.body.appendChild(line); }); ``` #### **常见问题解决** 1. **为什么返回空数组?** - ✅ 元素必须是`display:inline`(块级元素需改为`inline-block`) - ✅ 元素必须可见(检查`visibility: hidden`和`opacity:0`) - ✅ 元素需有具体尺寸(空元素无渲染框) 2. **获取坐标正确?** ```javascript // 解决:叠加滚动偏移量 const rect = element.getClientRects()[0]; const realTop = rect.top + window.scrollY; const realLeft = rect.left + window.scrollX; ``` 3. **与`getBoundingClientRect()`差异**: | 特征 | `getClientRects()` | `getBoundingClientRect()` | |---------------------|----------------------------------|-------------------------------| | 返回值 | 矩形集合(`DOMRectList`) | 单个矩形(`DOMRect`) | | 空元素 | 可能返回空数组 | 始终返回有效矩形[^2] | | 多行文本 | 每行返回独立矩形 | 返回整体包围盒 | | 适用元素 | 主要针对内联元素 | 所有可见元素 | 4. **边界异常处理** ```javascript // 安全访问建议 const rects = element.getClientRects(); if(rects.length > 0) { const firstRect = rects[0]; // 判断矩形有效性 if(firstRect.width * firstRect.height > 0) { // 执行操作 } } ``` #### **典型应用场景** 1. 文本编辑器中的光标定位 2. 代码高亮组件绘制 3. 响应式布局中的折行元素间距计算 4. 根据文本行数动态加载内容(虚拟滚动) #### **性能优化** 1. 避免在滚动事件中频繁调用(需用防抖) 2. 搭配`requestAnimationFrame`使用: ```javascript function updatePosition() { requestAnimationFrame(() => { const rects = element.getClientRects(); // 更新逻辑 }); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值