【问题标题】:jQuery get mouse position within an elementjQuery获取元素内的鼠标位置
【发布时间】:2011-05-14 01:46:53
【问题描述】:

我希望制作一个控件,用户可以在其中单击 div,然后拖动鼠标,然后松开鼠标以指示他们想要多长时间。 (这是用于日历控件,因此用户将指示某个事件的时间长度)

看起来最好的方法是在父 div 上注册一个“mousedown”事件,然后在 div 上注册一个“mousemove”事件,直到触发“mouseup”事件。 “mousedown”和“mouseup”事件将定义时间范围的开始和结束,当我关注“mousemove”事件时,我可以动态更改范围的大小,以便用户可以看到他们在做什么。我基于谷歌日历中事件的创建方式。

我遇到的问题是 jQuery 事件似乎只提供了参考整个页面的可靠鼠标坐标信息。有什么方法可以辨别坐标相对于父元素的含义吗?

编辑:

这是我正在尝试做的图片:

【问题讨论】:

    标签: jquery mouseevent


    【解决方案1】:

    如果您需要,这里还可以为您提供点的百分比位置。 https://jsfiddle.net/Themezly/2etbhw01/

    function ThzhotspotPosition(evt, el, hotspotsize, percent) {
      var left = el.offset().left;
      var top = el.offset().top;
      var hotspot = hotspotsize ? hotspotsize : 0;
      if (percent) {
        x = (evt.pageX - left - (hotspot / 2)) / el.outerWidth() * 100 + '%';
        y = (evt.pageY - top - (hotspot / 2)) / el.outerHeight() * 100 + '%';
      } else {
        x = (evt.pageX - left - (hotspot / 2));
        y = (evt.pageY - top - (hotspot / 2));
      }
    
      return {
        x: x,
        y: y
      };
    }
    
    
    
    $(function() {
    
      $('.box').click(function(e) {
    
        var hp = ThzhotspotPosition(e, $(this), 20, true); // true = percent | false or no attr = px
    
        var hotspot = $('<div class="hotspot">').css({
          left: hp.x,
          top: hp.y,
        });
        $(this).append(hotspot);
        $("span").text("X: " + hp.x + ", Y: " + hp.y);
      });
    
    
    });
    .box {
      width: 400px;
      height: 400px;
      background: #efefef;
      margin: 20px;
      padding: 20px;
      position: relative;
      top: 20px;
      left: 20px;
    }
    
    .hotspot {
      position: absolute;
      left: 0;
      top: 0;
      height: 20px;
      width: 20px;
      background: green;
      border-radius: 20px;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="box">
      <p>Hotspot position is at: <span></span></p>
    </div>

    【讨论】:

      【解决方案2】:

      我建议这样做:

      e.pageX - this.getBoundingClientRect().left
      

      【讨论】:

        【解决方案3】:

        一种方法是使用 jQuery offset 方法将 event.pageXevent.pageY 坐标从事件转换为相对于父级的鼠标位置。这是一个供将来参考的示例:

        $("#something").click(function(e){
           var parentOffset = $(this).parent().offset(); 
           //or $(this).offset(); if you really just want the current element's offset
           var relX = e.pageX - parentOffset.left;
           var relY = e.pageY - parentOffset.top;
        });
        

        【讨论】:

        • 是的,如果父元素的布局不能/不应该改变,这是个好主意!
        • 这个答案是否考虑了填充/边框?
        • 根据文档,offset 不考虑“在 body 元素上设置的边框、边距或填充”。我发布的答案在使用中没有遇到问题,但最好检查一下正在设置的答案。
        • 这不一定有效。 offset() 也是相对的,所以如果父元素是其他元素的子元素,这将给出错误的结果。请改用position()
        • @FlashThunder offset() 不是相对的,至少不是根据文档。此外,在 body 元素上没有任何边距或填充应该是标准做法。
        【解决方案4】:

        @AbdulRahim 的回答几乎是正确的。但我建议下面的函数作为替代(供进一步参考):

        function getXY(evt, element) {
                        var rect = element.getBoundingClientRect();
                        var scrollTop = document.documentElement.scrollTop?
                                        document.documentElement.scrollTop:document.body.scrollTop;
                        var scrollLeft = document.documentElement.scrollLeft?                   
                                        document.documentElement.scrollLeft:document.body.scrollLeft;
                        var elementLeft = rect.left+scrollLeft;  
                        var elementTop = rect.top+scrollTop;
        
                        x = evt.pageX-elementLeft;
                        y = evt.pageY-elementTop;
        
                        return {x:x, y:y};
                    }
        
        
        
        
                    $('#main-canvas').mousemove(function(e){
                        var m=getXY(e, this);
                        console.log(m.x, m.y);
                    });
        

        【讨论】:

        • 出色的改进,拯救了我的一天。
        • 差不多,给画布添加边距,你就靠边距了
        • 这是一段很棒的代码,非常感谢!
        【解决方案5】:

        此解决方案支持包括 IE 在内的所有主流浏览器。它还负责滚动。首先,它有效地检索元素相对于页面的位置,并且不使用递归函数。然后它获取鼠标点击相对于页面的 x 和 y 并进行减法得到答案,即相对于元素的位置(例如,元素可以是图像或 div):

        function getXY(evt) {
            var element = document.getElementById('elementId');  //replace elementId with your element's Id.
            var rect = element.getBoundingClientRect();
            var scrollTop = document.documentElement.scrollTop?
                            document.documentElement.scrollTop:document.body.scrollTop;
            var scrollLeft = document.documentElement.scrollLeft?                   
                            document.documentElement.scrollLeft:document.body.scrollLeft;
            var elementLeft = rect.left+scrollLeft;  
            var elementTop = rect.top+scrollTop;
        
                if (document.all){ //detects using IE   
                    x = event.clientX+scrollLeft-elementLeft; //event not evt because of IE
                    y = event.clientY+scrollTop-elementTop;
                }
                else{
                    x = evt.pageX-elementLeft;
                    y = evt.pageY-elementTop;
            }
        

        【讨论】:

          【解决方案6】:

          获取点击相对于当前点击元素的位置
          使用此代码

          $("#specialElement").click(function(e){
              var x = e.pageX - this.offsetLeft;
              var y = e.pageY - this.offsetTop;
          }); 
          

          【讨论】:

          • 你的回答帮助了我顺便说一句,接受的答案没有。谢谢 :) 我实际使用的是这个,而不是:var y = e.pageY - $(this).offset().top; 但是你的回答让我走上了正确的道路。
          【解决方案7】:

          我用了这段代码,很不错:)

              <script language="javascript" src="http://code.jquery.com/jquery-1.4.1.js" type="text/javascript"></script>
          <script language="javascript">
          $(document).ready(function(){
              $(".div_container").mousemove(function(e){
                  var parentOffset = $(this).parent().offset();
                  var relativeXPosition = (e.pageX - parentOffset.left); //offset -> method allows you to retrieve the current position of an element 'relative' to the document
                  var relativeYPosition = (e.pageY - parentOffset.top);
                  $("#header2").html("<p><strong>X-Position: </strong>"+relativeXPosition+" | <strong>Y-Position: </strong>"+relativeYPosition+"</p>")
              }).mouseout(function(){
                  $("#header2").html("<p><strong>X-Position: </strong>"+relativeXPosition+" | <strong>Y-Position: </strong>"+relativeYPosition+"</p>")
              });
          });
          </script>
          

          【讨论】:

            【解决方案8】:

            如果您将父元素设置为“位置:相对”,那么它将是您正在跟踪鼠标事件的内容的“偏移父元素”。因此 jQuery "position()" 将是相对的。

            【讨论】:

            • 嘿,Pointy,感谢您的回复。根据您的措辞,您的建议听起来与 jball 建议的不同,但我不明白如何,您能详细说明一下吗?再次感谢
            • @DutrowLLC,Pointy 建议将父元素的样式更改为 "position:relative"。然后,jQuery 位置将报告其相对于父元素而不是页面的位置。我回答的措辞很差,这意味着它与 Pointy 的解决方案直接相关,但是当您不能或不想依赖父元素的样式属性时,它是一种计算偏移量的方法。
            • 那么如果我设置“position:relative” jQuery 会在所有浏览器中正确报告相对位置吗?我问的原因是因为 jQuery 文档似乎暗示所有浏览器中唯一可靠的鼠标位置是与浏览器窗口本身相关的位置。
            • 具有“位置:相对”的框将通过相对于相对父框的内容矩形进行子框的“顶部”和“左侧”(等)设置。
            • 我可能做错了什么,但这似乎不适用于 Firefox。我有“位置:相对;”在父级中设置,firefox 报告 event.pageX 和 event.clientX 相同(相对于页面的顶部,左侧)并将 event.offsetX 报告为未定义
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-05-12
            • 1970-01-01
            • 2014-10-14
            • 1970-01-01
            • 2016-08-24
            • 1970-01-01
            相关资源
            最近更新 更多