我有一段很长的文本,并想为用户提供阅读帮助:当前行应该被突出显示。为了简化,我只使用鼠标的Y坐标(这样,鼠标指针不会妨碍)。我有一个ID为content
的大DIV,填满整个宽度,一个小DIV,类名为content
,用于文本(在此处查看示例)。
我正在使用jQuery 1.4。如何突出显示最接近当前鼠标位置的文本行?
我不确定jQuery是否能够帮助到你,但是你可以查看在MSDN和MDC上记录的element.getClientRects
方法。更具体地说,MSDN上的this example有点类似于你想要实现的效果,它使用了一个巧妙的z-index元素来突出显示行,该元素位于getClientRects()
返回的坐标下的文本后面。
通过循环遍历文档中onmousemove
返回的TextRectangle对象,并检查鼠标光标的y值是否大于每个矩形的顶部并且小于底部,然后将巧妙的z-index div移动到相同的位置/高度,您应该可以实现相同的效果。
所有主流浏览器都支持getClientRects()
。
已更新 - 可在Chrome、IE6/7/8、Firefox、Opera和Safari中工作。在其他浏览器中遇到的初始问题与DIV
需要设置为display: inline
有关。
再次更新 - 我不得不参考这个答案来回答一些新问题,所以我花时间更新了它以在窗口调整大小时重新计算行数。看起来其他人也在尝试,现在已经是第15版。
onresize
处理程序来重新填充 lines
变量,这样就会非常稳定。 - Peter Bailey我不认为你能在没有明确换行的情况下实现这一点(即,换行符或<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>
<span>
或<div>
元素,该元素具有:hover
CSS类。span.line:hover { background-color: lightblue; }
mouseover
和mouseout
事件来实现。getClientRects()
的示例答案 - 这样更简洁,而且我认为计算并不昂贵,因为返回的集合仅包含具有静态属性的对象。 - Andy E
getClientRects()
)适用于具有不同行高的文本。 - Aaron Digulla