Как я могу выделить строку текста, который является самым близким к мыши?

У меня есть длинный текст, и я хотел бы предложить пользователю справку чтения: текущая строка должна быть выделена. Для помощи я буду просто использовать координату Y мыши (этот путь, указатель мыши не собирается мешать). У меня есть большой DIV с идентификатором content который заполняет общую ширину и маленький DIV с классом content для текста (см. здесь для примера).

Я использую jQuery 1.4. Как я могу выделить строку текста, который является самым близким к текущему положению мыши?

7
задан Aaron Digulla 16 March 2010 в 17:00
поделиться

3 ответа

Не уверен, что Здесь вам очень поможет jQuery, но вы можете взглянуть на метод element.getClientRects , описанный в MSDN и MDC . В частности, этот пример в MSDN в некотором роде похож на то, что вы хотите достичь, выделяя строки с помощью хитроумного z-индексированного элемента div , который идет за текстом в координатах возвращается getClientRects () .

Вы должны иметь возможность достичь того же, перебирая объекты TextRectangle, возвращенные в документе onmousemove , и проверяя, является ли значение y курсора мыши> верхним и <нижним каждый прямоугольник и перемещая умно проиндексированный по оси z div на ту же позицию / высоту.

Все основные текущие браузеры поддерживают getClientRects () .


http://jsbin.com/avuku/15

ОБНОВЛЕНО - работает в Chrome, IE6 / 7/8, Firefox, Opera, Safari.Первоначальные проблемы, которые у меня были в других браузерах, были связаны с тем, что DIV должен был быть display: inline .
ОБНОВЛЕНИЕ СНОВА - мне пришлось обратиться к этому ответу для некоторых новых вопросов, поэтому я нашел время, чтобы обновить его, чтобы пересчитать строки при изменении размера окна.Похоже, что другие тоже играли, сейчас версия 15.

18
ответ дан 6 December 2019 в 06:49
поделиться

Лучший подход, который приходит на ум, это разделение каждой строки на или

элемент, который имеет :hover CSS класс с установленной настройкой "highlight":

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

Это было бы наименее затратным решением, так как браузер сам позаботится о выделении. Если вам нужны причудливые эффекты, вы можете добиться этого, добавив события mouseover и mouseout к каждой строке.

Сложная часть, конечно, заключается в разделении содержимого на строки с разрывом строки браузера. Это нужно делать динамически, чтобы строки действительно отражали позиции, в которых браузер разрывает текст.

Возможно, принятый ответ на этот вопрос - шаг в правильном направлении:

Получение конкретной строки с помощью jQuery

Как это работает:

Он проходит через весь элемент (фактически, клон элемента), вставляя элемент в каждое слово. Верхнее смещение span'а кэшируется - когда это смещение меняется, мы можем считать, что находимся на новой строке.

3
ответ дан 6 December 2019 в 06:49
поделиться

Я не понимаю, как вы могли бы сделать это без явного переноса текста (например, новых строк или элементов
).

Насколько мне известно, DOM не может обнаружить, где конкретный фрагмент текста обернут: по символам или по пикселям, включая то, что я знаю о Range API - не говоря уже о динамическом характере текста, который может принимать, например, с функцией масштабирования текста в браузерах.

Но если бы вам каким-то образом удавалось генерировать / вставлять явные окончания строк, я думаю, у меня есть решение для вас.

РЕДАКТИРОВАТЬ

Благодаря потрясающей информации в ответе Пекки я собрал функциональный прототип, но у него есть существенная оговорка - работает только с текстовым контентом. Любой HTML-код, присутствующий в теле элемента, будет удален.

<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript"> google.load("jquery", "1.4.1"); </script>
<script type="text/javascript">

  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>' );
  });

</script>

<style type="text/css">
span.line:hover {
  background-color: lightblue;
}
</style>

<p style="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>
5
ответ дан 6 December 2019 в 06:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: