How can I highlight the line of text that is closest to the mouse?

后端 未结 3 1596
轮回少年
轮回少年 2020-11-30 05:01

I have a long text and I\'d like to offer the user a reading help: The current line should be highlighted. To make it easier, I\'ll just use the Y coordinate of the mouse (t

3条回答
  •  春和景丽
    2020-11-30 05:43

    I don't see how you could feasibly do this without explicitly-wrapped text (i.e., newlines or
    elements).

    To the best of my knowledge, there's no way for the DOM to discover where a specific piece of text has wrapped, character-wise nor pixel-wise - including what I know of the Range API - not to mention the dynamic nature text can assume, such as with the text-zooming feature of browsers.

    But if you could somehow manage to generate/inject explicit line-endings, then I think I have a solution for you.

    EDIT

    Thanks to the awesome information in Pekka's answer, I've cobbled together a functional prototype, but it has a significant caveat - works with plain-text content only. Any HTML present the body of the element will be stripped.

    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') +
              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.line {
      display: inline;
    }
    span.line:hover {
      background-color: lightblue;
    }
    
    

    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

提交回复
热议问题