如何获取文本区域内所选文本的屏幕坐标 [英] How to get the screen coordinates for the selected text within a textarea

查看:24
本文介绍了如何获取文本区域内所选文本的屏幕坐标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,我正在尽最大努力弄清楚如何在文本区域字段中获取突出显示单词的X/Y

这是我当前的代码:

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
<script type="text/javascript">
var X = 0;
var Y = 0;

function selectHTML() {
    try {
        if (window.ActiveXObject) {
            var c = document.selection.createRange();
            return c.htmlText;
        }

        X = getSelection().getRangeAt(0).endOffset;
        Y = getSelection().getRangeAt(0).startOffset;
        w.surroundContents(nNd);

        return nNd.innerHTML;
    } catch (e) {
        if (window.ActiveXObject) {
            return document.selection.createRange();
        } else {
            return getSelection();
        }
    }
}

function FindTextInsideField() {
    var str = document.getElementById("FindText").value;
    var supported = false;
    var found = false;

    if (window.find) {
        supported = true;
        found = window.find(str);

        let pos = document.getElementById("FindText").value.indexOf(str);

        if (pos >= 0) {
            document.getElementById("FindText").setRangeText(str, pos, pos + 4, "select");
            document.getElementById("FindText").focus();
        }

        $('#FindText').val("");
    } else {
        if (document.selection && document.selection.createRange) {
            var textRange = document.selection.createRange();

            if (textRange.findText) {
                supported = true;

                if (textRange.text.length > 0) {
                    textRange.collapse(true);
                    textRange.move("character", 1);
                }

                found = textRange.findText(str);

                if (found) {
                    textRange.select();
                }
            }
        }

        $('#FindText').val("");
    }

    if (supported) {
        if (!found) {
            alert("The following text was not found:
" + str);
            $('#FindText').val("");
        }
    } else {
        alert("Your browser does not support this example!");
        $('#FindText').val("");
    }
}

function findXY() {
    var mytext = selectHTML();
    $('#_findXY').val("X = " + X + "  Y = " + Y);
}
</script>
</head>
<body>
 <textarea id = "paragraph_text" name = "paragraph_text" cols = "100" rows = "30" > Lorem ipsum dolor sit amet, eam iusto regione at.Mei id clita legendos.His ipsum neglegentur id, elit oblique no eos.Eum at clita eruditi.Vix quem hinc ex, meliore deserunt vix id, ei error ludus impetus ius.At evertitur elaboraret mel, sonet dolorum repudiandae mea at.
An iusto menandri repudiare mel, eu iisque definiebas pri, semper convenire eam ne.In ius percipit consequat.Ut sumo offendit quo.In duo epicuri nostrum eligendi, essent regione sed no.
In exerci doming splendide sit, mel omnes delicatissimi ei, at virtute vulputate efficiantur his.Quo possim civibus eu, hinc soluta ius ex.Ea quem dolor veniam mel.Sea ex paulo labores laboramus, te illud ludus mel.
Quo vidit nostrum postulant no, paulo doctus diceret vim et, sumo nullam reprehendunt in mei.Eu vis amet commune delicatissimi.Falli impedit in sea.Soluta appareat phaedrum ea sea.Sea facete postulant necessitatibus at, sea veri probo no.

---------------------------------------------------------------------------------------------- -

 </textarea >
 <br/>
 <input type = "text" id = "FindText" value = "percipit" size = "20" / >
 <button onclick = "FindTextInsideField();" > Find! </button>
 <input type = "text" style = "margin-left: 30px;" id = "_findXY" value = "" size = "20" readonly />
 <button onclick = "findXY();" > Get X / Y cords </button>
</body>
</html>

突出显示单词效果很好。您可以将您想要搜索的任何单词放在文本区域内。但是,一旦您按下获取X/Y线,它将显示X=5 Y=5,这是不正确的,因为根据codePen代码示例,它应该位于X=~250px by Y=~80px区域中。

有人知道如何解决这个问题吗?或者它是可解决的吗?

推荐答案

第一个问题:startOffsetendOffset与所选内容在屏幕上的位置无关。相反,它们与选择开始和结束的startContainerendContainer中的字符或节点位置有关。这允许您确定跨越多个元素的选择的开始和结束字符或节点索引(假设选择从段落的粗体区域开始,并在其外部结束,startOffset将是粗体元素文本内的索引,endOffset将是粗体元素之后的Text范围内的索引)。

好消息:在Range对象上有一个名为getBoundingClientRect的实验函数,它可以获取当前选定内容周围的边框的屏幕坐标。

问题:不幸的是,至少在Google Chrome中,当选择位于textareainput内时,getBoundingClientRect不会返回准确的坐标。因此,除非您可以避免使用textarea,例如通过使用内容可编辑的div(请参阅:https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Editable_content),否则此解决方案可能不适用于您。

疯狂的替代方法:Canvas对象具有测量文本尺寸的工具,因此,如果您真的是顽固的人,理论上可以测量textarea中包含的文本的尺寸,包括模拟换行行为,以便独立计算所选文本在textarea内的位置(不要忘记考虑滚动偏移量)。


下面是一个代码段,它直观地演示了选定Range对象在更改时的状态。

数据-lang="js"数据-隐藏="假"数据-控制台="假"数据-巴贝尔="假">
var outline = document.getElementById('selection_outline');
var start_container = document.getElementById('start_container');
var end_container = document.getElementById('end_container');
var start_offset = document.getElementById('start_offset');
var end_offset = document.getElementById('end_offset');

document.addEventListener('selectionchange', function() {
  var selection = document.getSelection();
  if (selection) {
    var range = selection.getRangeAt(0);
    if (range) {
      var bounds = range.getBoundingClientRect();
      outline.style.top = `${bounds.top + window.scrollY}px`;
      outline.style.left = `${bounds.left + window.scrollX}px`;
      outline.style.width = `${bounds.width}px`;
      outline.style.height = `${bounds.height}px`;
      
      start_container.value = range.startContainer.tagName || range.startContainer.parentNode.tagName;
      end_container.value = range.endContainer.tagName || range.endContainer.parentNode.tagName;
      
      start_offset.value = range.startOffset;
      end_offset.value = range.endOffset;
    }
  }
})
#selection_outline {
  position: absolute;
  border: 2px solid red;
  pointer-events: none;
}

.flow-wrap-row {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}

.flow-wrap-row > * {
  white-space: nowrap
}

.flow-wrap-row > li {
  margin-right: 1.5em;
}

ul {
 padding-left: 1.5em;
}

input {
 width: 80px;
}
<p>This is <b>a complex element</b> with lots of selectable text <i>and nested, <b> and double nested</b> elements</i>!!!</p>
<textarea cols="60" rows="5">Here is a text area with some simple content.</textarea>
<div contenteditable="true">Here is a contenteditable div with some simple content.</div>
<ul class="flow-wrap-row">
  <li><label>startContainer: <input id="start_container" type="text" /></label></li>
  <li><label>endContainer: <input id="end_container" type="text" /></label></li>
  <li><label>startOffset: <input id="start_offset" type="text" /></label></li>
  <li><label>endOffset: <input id="end_offset" type="text" /></label></li>
</ul>
<div id="selection_outline"></div>

这篇关于如何获取文本区域内所选文本的屏幕坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆