鼠标悬停时突出显示单行

4

当鼠标悬停在多行段落中的某一行该行中的任何单词上方)时,我想更改该行的背景颜色 - 是否可以使用JQuery / JS实现?

如果可以,要如何操作?

编辑: 为了澄清,我想在鼠标悬停在任何一行时都会高亮显示。
该脚本将动态隔离光标所在的行,并在鼠标悬停在其上时应用临时样式。

第二次编辑:
以下是示意图 -
enter image description here


请定义一行。 - Vlad
@Vlad 是浏览器呈现并被用户所看到的一行内容。 - Acidic
看看这个是否有帮助:https://dev59.com/4XI-5IYBdhLWcg3wNle1 - Vlad
4个回答

3

这是一场艰苦的战斗,但我想出了一种方法,可以在容器上不需要任何样式要求(包括字体、对齐等)的情况下完成操作。

虽然不是完美的解决方案,但希望它能满足您的需求。

var
    //Keeps the content (individual spans) as they are built.
    $keeper = $("<div>"),
    //Used to measure span width for comparison to container.
    $measurer = $("<div>"),
    //The container of the text content
    $p = $("p"),
    //An individual line of the content
    $line = $("<span>").appendTo($measurer),

//make this "invisible," but allow for measurement against container width
//with no restriction on measurer's own width (fixed)
$measurer.css({'position': 'fixed', 'top': '100%'}).appendTo("body");

//Iterate through each "word" derived from splitting on any space.
$p.text().split(/\s/).forEach(function (elem) {
    //Start forming line text.  Don't forget word spacing
    $line.text($line.text() + elem + ' ');

    //Enough words to make the line width longer than the p width.
    //This indicates the end of "line."
    if ($line.width() > $p.width()) {
        //Remove the last word.
        $line.text(function (_, text) {
            return text.slice(0, text.lastIndexOf(elem));
        });

        //Keep the currently formed line to add back later
        $line.appendTo($keeper);

        //Create a new line for measuring
        $line = $("<span>");
        $line.text(' ' + elem).appendTo($measurer);
    }
});
//Append any leftover words not big enough to form a whole line
$keeper.append($measurer.html());
//Add back content
$p.html($keeper.html());
//cleanup
$keeper.remove();
$measurer.remove();

http://jsfiddle.net/6Cx3h/2/

如果容器的宽度依赖于窗口大小,您还可以在窗口调整大小时执行此操作。

(您可以在http://jsfiddle.net/6Cx3h中看到我使用高度而不是宽度的尝试)


1
每一行都应该是一个单独的标签,如果你想的话可以使用<span>,然后用css(比javascript或jQuery更好)来实现。
span:hover{
  background-color: #ccc;
}

很遗憾,这是不可能的。有成千上万行代码,而且它们的宽度在未来可能会发生变化。 - Acidic

1
这完全取决于您的文本最初的格式。从您展示的屏幕截图来看,我认为文本被包裹在一个强制换行的元素中。在这种情况下,整个文本中没有真正的“新行”。如果元素的大小发生变化,情况会改变...例如,您现在正在阅读的文本是在网站的限制范围内包裹的...
但是,如果我要插入自己的换行符,则以下方法可能会有用。
// extract the text
var paragraph = $("#text").text();
// split the text into lines by searching for linebreaks
var lines = paragraph.split(/\r?\n/);
// clear the original text
$("#text").text('');
$.each(lines,function(index,elem){
  if (elem != ''){
    // for each line, wrap it with a span and bring back the linebreak
    $("#text").append('<span>'+elem+'</span><br/>');      
  }
});

现在你需要做的就是制作一些CSS规则来突出显示鼠标悬停在span元素上的效果 -
span:hover { background:#DDD }

一个实时示例


如果你打算在每一行添加一个<br/>,为什么不添加一个<span>呢?我觉得这不是Acidic正在寻找的。 - otinanai
@oti - 我不明白你的意思...我正在添加一个span。 - Lix
我对性能不是太确定...你可能需要自己测试一下... - Lix
哦,实际上,你的编辑是正确的。我的示例中的换行是由浏览器通过段落的宽度强制执行的;在文本本身中没有任何内容表明新行从哪里开始。 - Acidic
我的意思是该段落没有格式。如果您可以使用换行符进行格式化,为什么不使用<span>标签进行格式化呢? - otinanai

0

您可以通过创建一个块,将其放置在每行文本的后面,来模拟非格式化段落中单行文本的突出显示。该块的大小与您的 p line-height 相同,并根据鼠标 y-位置更改 top 位置。这种方法不能被视为本地突出显示,但它比其他建议具有一些优点。首先,它可以适应任何文本。其次,即使在调整流体文本块的大小后,它也可以计算出行数。第三,您可以保持文本干净,没有任何额外的标记(<br/>)或其他 breaks

HTML 代码:

<p>Some long non-formatted - fluid text</p>

CSS:

p {
    position:relative;
    text-align:justify;
    font: 14px/18px Arial; /*Line-height is essential to be defined because not all browsers translate the default value in px - e.g. Chrome returns "normal" and FF returns pixels*/
}
p span {  /*The highlighter*/
    background:yellow; /*Highlight color*/
    display:none; /*Hide it until we have a hover*/
    position:absolute;
    left:0;
    z-index:-1; /*Place it behind the text*/
}

jQuery:

//get the line-height
var theLineheight = $('p').css('line-height'); 
//strip it from the 'px'
var Lineheight = parseInt(theLineheight); 
//get the text height
var thePheight = $('p').height(); 
//update the height after resize
window.onresize = function () {
    return thePheight = $('p').height(); 
}
//create the highlight box
$('p').append('<span style="height:' + theLineheight + ';width:100%"></span>'); 
//detect mouse movement in the text container
$('p').mousemove(function (e) {
    //show the highlighter
    $('p span').show();
    //get the mouse position
    mouseTop = e.pageY - this.offsetTop;
    //round it to a line-height scale
    topPos = Math.ceil(mouseTop / Lineheight) * Lineheight - Lineheight;
    //position the highlighter vertical
    $('p span').css('top', topPos + 'px');
    //hide the highlighter when mouse is at the end of the text - including the space that highlighter takes
    if (topPos > (thePheight - Lineheight)) {
        $('p span').hide();
    }
//hide the highlighter when mouse is not over the text
}).mouseout(function (e) {
    $('p span').hide();
});

这是演示:http://jsfiddle.net/gh8gZ/1/ 我能看到的唯一缺点是,当您有一个带有空行的文本块时,它们也会被突出显示,并且突出显示的区域占据整行的宽度 - 尽管这对我来说并不影响,但我必须指出这不是完美的解决方案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接