如何突出显示最接近鼠标的文本行?

问题描述 投票:7回答:3

我有很长的文字,我想为用户提供阅读帮助:当前行应突出显示。为了简化操作,我将只使用鼠标的Y坐标(这样,鼠标指针不会挡住)。我有一个ID为content的大DIV,它填充了整个宽度,还有一个文本为content的小DIV,用于文本(see here for an example)。

我正在使用jQuery 1.4。如何突出显示与当前鼠标位置最接近的文本行?

javascript html text line highlight
3个回答
18
投票

[不确定jQuery是否会在这里帮助您很多,但是您可以看看element.getClientRectsMSDN中记录的MDC方法。更具体地说,MSDN上的this example类似于您要实现的目标,它使用巧妙的z索引div元素突出显示了行,该元素位于getClientRects()返回的坐标后面的文本之后。

您应该能够通过遍历文档onmousemove中返回的TextRectangle对象并检查鼠标光标的y值是否大于或小于每个矩形的底部并移动矩形来实现相同的目的。巧妙地将z索引的div设置到相同的位置/高度。

当前所有主流浏览器都支持getClientRects()


http://jsbin.com/avuku/15

UPDATED-在Chrome,IE6 / 7/8,Firefox,Opera和Safari中均可使用。我在其他浏览器中遇到的最初问题与DIV需要为display: inline有关。再次更新-对于一些较新的问题,我不得不参考此答案,因此我花了一些时间对其进行更新,以重新计算窗口调整大小上的行数。看起来其他人也一直在玩,现在是15版。


6
投票

我不知道如果没有显式包装的文本(即换行符或<br>元素),如何可行地做到这一点。

据我所知,DOM无法以字符为单位[以像素为单位-包括我对Range API所知的内容-来发现特定文本的包装位置。提及文本可以假定的动态性质,例如浏览器的文本缩放功能。

但是,如果您能够以某种方式设法生成/注入明确的行尾,那么我想我有一个适合您的解决方案。

编辑

由于Pekka的回答中提供了很棒的信息,我已经拼凑了一个功能原型,但它有一个重要的警告-仅适用于纯文本内容。表示元素正文的所有HTML都会被剥离。

jQuery.fn.wrapLines = function( openTag, closeTag ) { var dummy = this.clone().css({ top: -9999, left: -9999, position: 'absolute', width: this.width() }).appendTo(this.parent()) , text = dummy.text().match(/\S+\s+/g); var words = text.length , lastTopOffset = 0 , lines = [] , lineText = '' ; for ( var i = 0; i < words; ++i ) { dummy.html( text.slice(0,i).join('') + text[i].replace(/(\S)/, '$1<span/>') + text.slice(i+1).join('') ); var topOffset = jQuery( 'span', dummy ).offset().top; if ( topOffset !== lastTopOffset && i != 0 ) { lines.push( lineText ); lineText = text[i]; } else { lineText += text[i]; } lastTopOffset = topOffset; } lines.push( lineText ); this.html( openTag + lines.join( closeTag + openTag ) + closeTag ); }; $(function() { $('p').wrapLines( '<span class="line">', '</span>' ); });
span.line {
  display: inline;
}
span.line:hover {
  background-color: lightblue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p style="max-width:400px">
 one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twenty-one twenty-two twenty-three
</p>

3
投票
想到的最好的方法是将每一行拆分为<span><div>元素,该元素具有:hover CSS类,并且设置了“突出显示”设置:

span.line:hover { background-color: lightblue; }

这将是最便宜的解决方案,因为浏览器将自行处理所有突出显示的内容。如果您想要奇特的效果,仍然可以通过向每行添加mouseovermouseout事件来实现。 

当然,困难的部分是在浏览器的换行符处将内容分成几行。您需要动态地执行此操作,以便这些行实际反映浏览器将文本断开的位置。

也许这个问题的公认答案是朝正确方向迈出的一步:

Getting a specific line using jQuery

如何运作:

它遍历整个元素(实际上是元素的克隆),并在每个单词中插入一个元素。跨度的最高偏移量已缓存-当此偏移量更改时,我们可以假定我们在新行上。

© www.soinside.com 2019 - 2024. All rights reserved.