Javascript 输入类型文本(非文本区域)中以像素为单位的插入符号位置

Javascript 输入类型文本(非文本区域)中以像素为单位的插入符号位置,javascript,html,textinput,caret,Javascript,Html,Textinput,Caret,更新:的副本 TL;DR-使用极其轻量级和健壮的组件库,它现在也支持。演示 有没有办法知道插入符号在HTML文本字段中的位置 <input type='text' /> 我想根据插入符号的位置以像素为单位定位(并重新定位)一个div 注意:我不想知道字符或中的位置。我想知道元素中像素的位置 使用不可见的人造元素 您可以通过使用绝对定位的不可见(使用可见性而不是显示)人造元素来实现这一点,该人造元素具有与输入文本框相同的CSS属性(字体、左边框和左填充) 这是该脚本如何工作的

更新:的副本

TL;DR-使用极其轻量级和健壮的组件库,它现在也支持
。演示


有没有办法知道插入符号在HTML文本字段中的位置

<input type='text' /> 

我想根据插入符号的位置以像素为单位定位(并重新定位)一个div

注意:我不想知道字符或
中的位置。我想知道
元素中像素的位置

使用不可见的人造元素 您可以通过使用绝对定位的不可见(使用
可见性
而不是
显示
)人造元素来实现这一点,该人造元素具有与输入文本框相同的CSS属性(字体、左边框和左填充)

这是该脚本如何工作的起点。
它可以在Chrome和Firefox中正常工作。它也可以在IE9+中工作

InternetExplorer8(及以下版本)需要从输入文本框中文本的开头获取插入符号位置。我甚至在顶部添加了一个米,每10像素显示一条线,这样你就可以看到它的测量是否正确。请注意,行在1、11、21、,。。。像素位置

本例所做的实际上是将文本框中的所有文本提取到插入符号位置,并将其放入faux元素中,然后以像素为单位测量其宽度这将使您从文本框的左侧偏移。

当它将文本复制到faux元素时,它也会将普通空格替换为非打断空格,因此如果您将插入符号放置在空格之后,它们实际上会被渲染,否则您会得到错误的位置:

var faux = $("#faux");
$("#test").on("keyup click focus", function(evt) {
    // get caret offset from start
    var off = this.selectionStart;

    // replace spaces with non-breaking space
    faux.text(this.value.substring(0, off).replace(/\s/g, "\u00a0"));
});​
注意人造的正确尺寸

  • 填充物
  • 边界
  • 边际
为了得到正确的值,已经删除了,否则元素将太宽。元素的框必须在其包含的文本之后结束

从输入框开始,插入符号的位置(以像素为单位)很容易从以下位置获得:

faux.outerWidth();
问题 但有一个问题。我不知道当文本框中的文本被滚动(太长)并且插入符号不在文本的末尾,而是在文本框和插入符号之间时,如何处理这种情况。。。如果在末尾,则插入符号位置始终处于可能的最大位置(输入宽度减去右侧尺寸-填充、边框、边距)

我不确定是否有可能在文本框中获得文本滚动位置?如果可以的话,这个问题也可以解决。但我不知道有什么解决办法

希望这能有所帮助。这里有一个有效的例子

为了找到插入符号的位置,我对输入中的字母进行了计数,并将该值乘以1个字母的大小

在那之后,我们把div移到了那个地方

<html>
<head>
<style type="text/css">
body { font-size: 12px; line-height: 12px; font-family: arial;}
#box { width: 100px; height: 15px; position: absolute; top: 35px; left: 0px; background: pink;}
</style>
<script type="text/javascript" src="jquery-1.7.1.js"></script>
<script type="text/javascript">
$(document).ready(function(){
var letter_size = 6;
$("input[type='text']").keyup(function(e) {
    move_size = $(this).val().length * letter_size;
    $('#box').css({'left': move_size+'px'}); 
});
});
</script>

</head>
<body>
<input type="text" />
<div id="box">
/ move 
</div>
</body>
<html>

添加了一个隐藏容器,在其中插入输入值。之后,我得到容器的宽度并相应地移动DIV,那么canvas 2D呢?它具有用于绘制测量文本的API。你可以用这个。设置相同的字体,字体大小,你们应该能够从文本框中测量字符串的宽度

      $('body').append('<canvas id="textCanvas" width="100px" height="100px">I\'m sorry your browser does not support the HTML5 canvas element.</canvas>');
      var canvas = document.getElementById('textCanvas');
      var ctx = canvas.getContext('2d');
      ctx.measureText(text);
      var width = mes.width;
$('body').append('很抱歉,您的浏览器不支持HTML5画布元素');
var canvas=document.getElementById('textCanvas');
var ctx=canvas.getContext('2d');
ctx.measureText(文本);
var宽度=mes宽度;
我使用这种解决方案来获取一些文本的宽度,以便在WebGL中绘制它。我工作得很好,但我从未测试过当文本对于画布上下文来说太大时会发生什么,我认为它会很好,因为它是测量文本的API。但是何知道你应该彻底检查一下!:)

您可以使用
。这样,您就可以使用
window.getSelection()
getRangeAt
以及
getclientracts
来获取位置。这应该适用于大多数现代浏览器,包括IE9+:

function getCaret() {
    var caret = caret = {top: 0, height: 0},
        sel = window.getSelection();
    caret.top = 0;
    caret.height = 0;
    if(sel.rangeCount) {
        var range = sel.getRangeAt(0);          
        var rects = range.getClientRects();
        if (rects.length > 0) {
            caret.top = rects[0].top;
            caret.height = rects[0].height;
        } else {
            caret.top = range.startContainer.offsetTop - document.body.scrollTop;
            caret.height = range.startContainer.clientHeight;
        }
    }
    return caret;
}
(请记住,我所做的这个项目是针对Mobile Safari的,它使用了一个大型contenteditable视图。您可能需要调整它以满足您的需要。这更多是为了演示如何获取X和Y坐标。)

对于IE8及以下版本,IE有一个专有的API来获取相同的信息


棘手的部分是确保元素只允许纯文本。特别是粘贴事件。当span失去焦点(onblur)时,您希望将内容复制到隐藏字段中,以便发布。

详细阐述我的上述评论,我想下面应该可以

为了显示原理,我省略了格式化,因此可能需要将元素(id=“spacer”)颜色设置为
#fffff e
,可能添加了一些前导空格像素等。。。但是卡雷特现在会按比例移动——只要id的测试和间隔使用相同的字体

当然,我们不知道[px]中的距离,但是我们能够定位内容(本例中为carret)与比例字体的宽度完全一致,因此如果这是最终目标(如OP第3行所述),那么。。。。瞧

<html>
    <head>
        <title></title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
        <script type="text/javascript">
            function adjust()
            {
                document.getElementById('spacer').innerHTML=document.getElementById('test').value;
            }
        </script>
        <p>
            <input name="test" id="test" type="text" onkeyup="adjust()" /> Test <br />
            <span id="spacer"></span>^here
        </p>
    </body>
</html>

函数调整()
{
document.getElementById('spacer').innerHTML=document.getElementById('test').value;
}

测试
^这里

更新:

<span id="spacer" style="color: #FFFFFF"></span>


这将使间隔符在白色背景上不可见,但不会阻止用户通过选择跨度元素高亮显示间隔符文本。保留使间隔棒不可选择的任务-有一个很好的解决方案

类似的问题涵盖了您的问题:


Ivlev,它没有以像素为单位告诉我位置。您最初的帖子是关于
<html>
    <head>
        <title></title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
        <script type="text/javascript">
            function adjust()
            {
                document.getElementById('spacer').innerHTML=document.getElementById('test').value;
            }
        </script>
        <p>
            <input name="test" id="test" type="text" onkeyup="adjust()" /> Test <br />
            <span id="spacer"></span>^here
        </p>
    </body>
</html>
<span id="spacer" style="color: #FFFFFF"></span>