代码之家  ›  专栏  ›  技术社区  ›  Terry King

如何使用scrollIntoView从文本节点

  •  0
  • Terry King  · 技术社区  · 2 年前

    我不知道如何获得文本节点的元素,但我可以获得父元素。

    我已经编写了一个javascript例程来使用范围进行选择。所以我有一个开始节点和结束节点,它们是用document.createTreeWalker(rootnode,NodeFilter.SHOW_TEXT,null,false)获得的。

    我想使用scrollIntoView(),但似乎只能从元素中调用它。所以目前我正在使用startNode.parentElement.scrollIntoView。

    let range = new Range()
    range.setStart(startNode, startPos)
    range.setEnd(endNode, endPos)
    document.getSelection().removeAllRanges()
    document.getSelection().addRange(range)
    startNode.parentElement.scrollIntoView({ behavior: 'instant', block: 'start', inline: 'start' })
    

    当标签很小时一切都很好,但如果它是一段大的文本,那么父位置可能离实际元素的位置很远。有没有办法获取文本节点的元素,这样我就可以调用scrollIntoView?

    作为解决方案,我使用range.getBoundingClientRect(),然后设置页面的scrollTop。

    let bb=range.getBoundingClientRect()
    pagetop.parentElement.scrollTop = bb.y+pagetop.parentElement.scrollTop-130 // 130 fudge value
    

    它有效:),但我宁愿使用scrollIntoView,或者至少更好地了解我做错了什么。

    2 回复  |  直到 2 年前
        1
  •  0
  •   Iman Hedeshy    2 年前

    要在JavaScript中滚动到文本节点,您不能使用 scrollIntoView() 直接在文本节点上。但是,您可以通过创建临时元素来使用变通方法。
    就像创建一个 <span> 元素,然后滚动到该位置,然后将其从DOM中删除。

    let range = new Range();
    range.setStart(startNode, startPos);
    range.setEnd(endNode, endPos);
    
    let tempSpan = document.createElement('span');
    range.insertNode(tempSpan);
    
    tempSpan.scrollIntoView({ behavior: 'instant', block: 'start' });
    tempSpan.remove();
    
    document.getSelection().addRange(range);
    
        2
  •  0
  •   jsejcksn    2 年前

    您可以使用 x y 的坐标 DOMRect 由返回 Range.prototype.getBoundingClientRect() 方法作为的参数 window.scroll() 像这样:

    const nodeStart = new Text("nee");
    const nodeEnd = new Text("dle");
    
    function createHaystack() {
      const paragraph = document.querySelector("p.haystack");
    
      for (let i = 0; i < 100; i += 1) {
        paragraph.append(new Text("hay ".repeat(50)));
      }
    
      paragraph.append(nodeStart, nodeEnd, " ");
    
      for (let i = 0; i < 100; i += 1) {
        paragraph.append(new Text("hay ".repeat(100)));
      }
    }
    
    function findNeedle() {
      const range = new Range();
      range.setStart(nodeStart, 0);
      range.setEnd(nodeEnd, nodeEnd.length);
      document.getSelection().removeAllRanges();
      document.getSelection().addRange(range);
    
      const rangeRect = range.getBoundingClientRect();
      window.scroll(rangeRect.x, rangeRect.y);
    }
    
    createHaystack();
    document.querySelector("button").addEventListener("click", findNeedle);
    body { font-family: sans-serif; }
    <button>Find needle</button>
    <p class="haystack"></p>