在CoffeeScript/JavaScript中使用鼠标光标位置作为范围起点

Using mouse cursor position as a range starting point in CoffeeScript/JavaScript

本文关键字:位置 光标 起点 范围 鼠标 CoffeeScript JavaScript      更新时间:2023-09-26

正如标题所述,我想使用光标的位置作为范围的起点。

现在有像这样的简单样本

<html>
  .
  .
   <p>The quick brown fox jumps over the lazy dog</p>
  .
  .
</html>

在CS/JS方面,我将事件侦听设置为鼠标移动,试图打印出光标位置的偏移量,但我没有使用正确的方法,最终得到undefinedno method error s。

再次,非常简单的CS暂时,因为我真的只是想测试一下。

$(document).ready ->
  $(document).mousemove ->
    target = event.target
    console.log("#{target.offset()}") // also tried .rangeOffset .offset

理想情况下,我想要一些可以输入到range.setStart()函数中的内容。

例如,如果我将鼠标悬停在fox中的f上,我希望偏移量返回为16,这样我就可以像range.setStart(target,16)那样设置范围的开始。

如果能为我指明正确的方向,我们将不胜感激。

编辑:在输入并提交后,我意识到期望元素给我回偏移信息是多么愚蠢我迷路了,请指引我。

经过大量的谷歌搜索和数小时的故障排除,我终于找到了一个适合我的解决方案。

函数document.caretPositionFromPoint()或Webkit的函数document.caretRangeFromPoint()从事件中获取X和Y坐标,并返回插入符号位置,然后我可以使用该位置创建范围的起点。

$(document).ready ->
  setRange = (event) ->
      if document.caretPositionFromPoint
        #for Firefox
      else if document.caretRangeFromPoint
        range = document.caretRangeFromPoint(event.pageX, event.pageY)
        targetNode = range.startContainer
        offset = range.startOffset
        range.setStart(targetNode, offset)
        range.setEnd(targetNode, 10) #just to test
        sel = window.getSelection()
        sel.removeAllRanges()
        sel.addRange(range)
    element = document.getElementById("content")
    element.addEventListener('mousemove', setRange, true) #eventlistener instead of .mousemove for event bubbling

您应该使用pageX或pageY,就像这个

$(document).ready ->
  $(document).mousemove (e) ->
    console.log("#{e.pageX}")
    console.log("#{e.pageY}")

如果您需要获得相对于div的位置,例如

$(document).ready ->
      $(document).mousemove (e) ->
        console.log("#{e.pageX - $('#divID').offset().left}")
        console.log("#{e.pageY - $('#divID').offset().top}")

应用到你的案例中,它会给你类似于的东西

$(document).ready ->
  $('p').mousemove (e) ->
    console.log("#{e.pageX - $('p').offset().left}")
    console.log("#{e.pageY - $('p').offset().top}")

将鼠标移到包含文本的段落上会使您的鼠标位于段落中

看看它在这里工作http://jsfiddle.net/zXnk9/


编辑

如果你需要获得你悬停的角色的索引,你可以使用这样的技巧:

将文本包装在一个与文本宽度完全相同的容器中

<span>The quick brown fox jumps over the lazy dog</span>

然后进行以下计算

$(document).ready ->
  // define the container for the text you are intersted in
  container = $('span')
  // on mouseover
  container.mouseover (e) ->
    // get container width
    container_width = container.width()
    // compute the avg character width base on the container width and the number of characters contained in your text. 
    // (If you have some complex formatting inside your container, you would have to adjust this calculation.)
    char_width = p_width / container.text().length
    // get the position of your mouse inside
    position_inside = e.pageX - container.offset().left
    // define the index of the character you are interested in
    char_index = Math.floor(position_inside / char_width) - 1
    // use it as you wish
    // print it for example
    console.log("#{char_index}")

你可以在这里检查它的工作情况。我已经将事件设置为点击,这样你就可以在福克斯的f上准确地尝试它,它返回16。http://jsfiddle.net/zXnk9/1/

编辑2:为了一种可靠的方式来做你正在尝试做的

加载文档时,将容器中的每个字符放入一个html节点中,如

$(document).ready ->
  // set your container
  container = $('span')
  // define a replacement text string
  replacement_container_text = ''
  // iterate over each character inside your container
  $(container.text().split('')).each (i, char) ->
    // put it inside a span and add it to your replacement text string
    replacement_container_text += '<span>' + char + '</span>'
  // set the replacement text string as the html content of your container
  // this replaces the original text with the initial text with each 
  // character wrapped into a span 
  // (which can then be caught as targets for your mousemove events)
  container.html(replacement_container_text)   

然后,您可以使用以下获取鼠标所在字符的索引

container.mousemove (e) ->
  range_start = container.children('span').index $(e.target)
  console.log(range_start)

这将适用于多行容器、段落等。

参见工作示例http://jsfiddle.net/2TBFV/