Как узнать, являются ли два текстовых узла визуально последовательными

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

Я использую Диапазоны для получения прямоугольников ( размер и положение), но между текстовыми узлами есть интервал (нижняя часть первого прямоугольника не соответствует верхней части второго).

Я попытался рассчитать этот интервал на основе line-height и font-size, но не смог получить такое же значение.

Вот JsFiddle с моей попыткой: https://jsfiddle.net/3behsxxq/5/

Есть ли способ рассчитать это расстояние?

ОТРЕДАКТИРОВАНО: В первом случае кода jsFiddle есть четыре строки («первый текст», «блок», «второй», «текстовый блок»), которые визуально следуют друг за другом, то есть визуально расстояние между ними одинаково, но число, которое я получаю, имеет разницу в 7 (в этом первом случае). Если я попытаюсь отбросить это пространство на основе разницы между line-height/font-size и значениями диапазона, они не совпадут, поэтому я не смогу этому противодействовать.

ОТРЕДАКТИРОВАНО 2. Контекст: На изображении ниже 6 линий имеют одинаковое расстояние между собой. Я ищу способ определить, что они являются частью одного и того же абзаца, независимо от структуры html (поскольку html может иметь элемент <p> или любой другой элемент для представления абзаца).

введите здесь описание изображения


person jcbp    schedule 01.09.2016    source источник
comment
Я думаю, что часть сложности здесь заключается в том, что размер шрифта в пикселях не совпадает с полной высотой от самого высокого надстрочного элемента (обычно d, b, l и т. д.) до самого нижнего подстрочного элемента (p, q). Ответы на этот вопрос о графическом дизайне весьма полезны: заголовок graphicdesign.stackexchange.com/questions/4035/   -  person Robin James Kerrison    schedule 20.09.2016
comment
Достаточно ли вам знать, что расстояние между прямоугольниками меньше, чем разница между высотой строки и размером шрифта?   -  person Robin James Kerrison    schedule 20.09.2016
comment
Спасибо за комментарий @RobinJamesKerrison. Я делаю тест, используя скрытый элемент с однострочным текстом, и создаю диапазон для этого элемента, чтобы получить соответствующую высоту. Мне бы хотелось найти способ получить это значение из стиля элемента, но я думаю, что в конечном итоге я использую это решение.   -  person jcbp    schedule 21.09.2016
comment
Вот связанный вопрос, который показывает, как использовать jQuery для определить расстояние по вертикали от верхней части экрана до верхней части элемента. Вы должны иметь возможность использовать это в сочетании с высотой элемента, чтобы определить, насколько ниже нижней части первого элемента начинается второй элемент.   -  person kmoser    schedule 09.09.2017
comment
У @kmoser есть отличная идея. Разве это не должно быть возможно с element.offsetTop & element.offsetLeft & getClientRects?   -  person admcfajn    schedule 06.01.2018
comment
определить визуально последовательные в терминах расстояния, и это можно выяснить из различных свойств смещения.   -  person aviya.developer    schedule 23.01.2019
comment
@jcbp вам нужно расстояние между двумя текстовыми узлами. Ваш вопрос неясен, пожалуйста, уточните.   -  person Maheer Ali    schedule 08.02.2019
comment
Я отредактировал пост для ясности.   -  person jcbp    schedule 12.02.2019
comment
Даже если два элемента визуально следуют друг за другом, что, если есть другой элемент, перекрывающий их оба через относительное или абсолютное позиционирование CSS?   -  person nnnnnn    schedule 19.02.2019
comment
@nnnnnn В моем конкретном случае я решаю это самостоятельно. Я думаю об этом как о двух разных проблемах.   -  person jcbp    schedule 19.02.2019
comment
Что ж, если есть 2 последовательных текстовых узла, они ДОЛЖНЫ быть в 2 отдельных элементах, иначе DOM превратит их в один текстовый узел. Один из способов измерить расстояние между ними — поместить каждый текстовый узел в элемент и найти расстояние между этими элементами, используя стандартные методы.   -  person alfadog67    schedule 11.04.2019
comment
Совершенно не уверен, чего вы пытаетесь достичь. Если вам нужен GAP между прямоугольниками, getBoundingClientRect() имеет свойства top и bottom. var getGap = function(textNode1, textNode2) { const r = document.createRange(); r.selectNode (textNode1); const {нижний} = r.getBoundingClientRect(); r.selectNode(textNode2); const {top} = r.getBoundingClientRect(); возврат верх – низ; }   -  person eavichay    schedule 01.05.2019
comment
@eavichay Спасибо за комментарий. Я просто снова редактирую сообщение, чтобы добавить больше ясности. Пожалуйста, см. Отредактировано 2 для контекста.   -  person jcbp    schedule 03.05.2019


Ответы (1)


var extractTextNodes = function(paragraph) {
  var nodes = [];
  function callback(node) {
    if (node.nodeType === Node.TEXT_NODE) {
      nodes.push(node);
    } else if (node.nodeType === Node.ELEMENT_NODE) {
      node.childNodes.forEach(callback);
    }
  }
  paragraph.childNodes.forEach(callback);
  return nodes;
};

var findParentParagraph = function(node) {
  var parent = node.parentElement;
  while (parent) {
    if (parent.tagName === "P") {
      return parent;
    }
    parent = parent.parentElement;
  }

  return null;
};

var areTextNodesSiblings = function(textNode1, textNode2) {
  var p = findParentParagraph(textNode1);
  if (!p) {
    return false;
  }

  var allTextNodes = extractTextNodes(p);
  var index1 = allTextNodes.indexOf(textNode1);
  var index2 = allTextNodes.indexOf(textNode2);
  if (index2 === -1) {
    return false;
  }
  return (index1 === index2 - 1) || (index1 === index2 + 1);
};

И просто вызовите areTextNodesSiblings, передав узлы.

Скрипт: https://jsfiddle.net/krmnve37/1/


В заголовке написано «визуально последовательно», но «ОТРЕДАКТИРОВАНО 2. Контекст» говорится, что узлы должны находиться в одном абзаце. Следующая функция проверит, находятся ли два узла только в одном абзаце, а не рядом друг с другом:

var areTextNodesInTheSameParagraph = function(textNode1, textNode2) {
  var p = findParentParagraph(textNode1);
  if (!p) {
    return false;
  }

  var allTextNodes = extractTextNodes(p);
  var index1 = allTextNodes.indexOf(textNode1);
  var index2 = allTextNodes.indexOf(textNode2);
  return index1 > -1 || index2 > -1;
};
person Dimitar Nestorov    schedule 10.05.2019