jQueryは要素内のマウス位置を取得します


165

ユーザーがdivの内側をクリックして、マウスをドラッグし、マウスを離して、何かにしたい期間を指定できるコントロールを作成したいと思っていました。(これはカレンダーコントロール用であるため、ユーザーは特定のイベントの長さを時間で示します)

これを行う最良の方法は、「mouseup」イベントがトリガーされるまで、divに「mousemove」イベントを登録する親divに「mousedown」イベントを登録することです。「mousedown」および「mouseup」イベントは、時間範囲の開始と終了を定義します。「mousemove」イベントに従うと、範囲のサイズを動的に変更して、ユーザーが何をしているかを確認できます。これは、Googleカレンダーでのイベントの作成方法に基づいています。

私が抱えている問題は、jQueryイベントがページ全体に関して信頼できるマウス座標情報しか提供しないように見えることです。親要素を基準にして座標が何であるかを見分ける方法はありますか?

編集:

ここに私がやろうとしていることの写真があります: 代替テキスト

回答:


305

1つの方法は、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;
});

2
はい、これは、親要素のレイアウトを変更できない、または変更できない場合に最適です。
先のとがった

2
この回答はパディング/ボーダーを考慮していますか?
LeeGee 2013年

10
ドキュメントによると、オフセットは「body要素に設定された境界線、マージン、またはパディング」を考慮していません。投稿された回答を使用中に問題が発生したことはありませんが、設定されている回答を確認することをお勧めします。
jball 2013年

2
これは機能する必要はありません。offset()も相対的なので、親が他の要素の子である場合、これは誤った結果をもたらします。position()代わりに使用してください。
Flash Thunder

1
@FlashThunder offset()は相対的ではなく、少なくともドキュメントによればそうではありません。また、body要素にマージンやパディングを付けないことも標準的な方法です。
James Watkins

18

現在のクリックされた要素に対するクリックの位置を取得
するにはこのコードを使用します

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

2
ところであなたの答えは私を助けました、受け入れられた答えはしませんでした。おかげで:)私が実際に使用したのはこれです、代わりに: var y = e.pageY - $(this).offset().top;しかし、あなたの答えは私を正しい道に導きました。
Solomon Closson

11

私はこのコードを使用しています、それはとてもいいです:)

    <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>

9

@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);
            });

1
見事な改善、私の日を救った。
Bud Damyanov 2016年

ほとんど、キャンバスにマージンを追加すると、マージンが足りなくなります
Benn

これはすばらしいコードの一部です。どうもありがとうございました。
ステファン

7

このソリューションは、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;
    }

3

親要素を「位置:相対」にすると、マウスイベントを追跡する対象の「オフセット親」になります。したがって、jQueryの "position()"はそれに相対的になります。


ちょっと先のとがった、あなたの応答をありがとう。あなたの言葉遣いに基づいて、あなたが提案していることはjballが提案したものとは異なるように聞こえますが、私はどのように理解していないのですか、詳しく説明できますか?ありがとうございました
Chris Dutrow、2010

@ DutrowLLC、Pointyは親要素のスタイルをに変更することを提案してい"position:relative"ます。jQueryの位置は、ページではなく、親要素を基準にした位置を報告します。私の答えの表現は貧弱です、それはそれがポインティのソリューションに直接関連していることを意味しますが、それはあなたが親要素のスタイル属性に依存することができない、またはしたくないときのオフセットを計算する方法です。
jball

「position:relative」を設定すると、jQueryはすべてのブラウザーで相対位置を正しく報告しますか?私が尋ねる理由は、jQueryのドキュメントでは、すべてのブラウザーで唯一信頼できるマウスの位置が、ブラウザーウィンドウ自体との関係であると示唆しているためです。
Chris Dutrow、2010

「position:relative」のボックスは、相対的な親ボックスのコンテンツ四角形を基準にして、子ボックスの「top」および「left」などを設定します。
ポインティ

私は何か間違ったことをしているかもしれませんが、これはFirefoxでは機能しないようです。「position:relative;」があります。親に設定すると、firefoxはevent.pageXとevent.clientXを同じように(ページの左上を基準として)レポートし、event.offsetXを未定義として報告します
Chris

2

これは、必要に応じて、ポイントのパーセント位置も提供するものです。 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>


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.