jQuery отримує положення миші в межах елемента


165

Я сподівався створити елемент управління, де користувач може натиснути всередину діва, потім перетягнути мишу, а потім підняти мишу, щоб вказати, як довго вони щось хочуть. (Це для керування календарем, тому користувач буде вказувати тривалість певної події у часі)

Схоже, найкращим способом зробити це було б зареєструвати подію "mousedown" на батьківському діві, який, в свою чергу, реєструє події "mousemove" на діві до тих пір, поки не буде запущено подію "mouseup". Події "mousedown" та "mouseup" визначатимуть початок та кінець часового діапазону, і коли я слідкую за подіями "mousemove", я можу динамічно змінювати розмір діапазону, щоб користувач міг бачити, що вони роблять. Я базував це на тому, як створюються події в google-календарі.

Проблема у мене полягає в тому, що подія jQuery, здається, надає лише надійну інформацію про координати миші по відношенню до всієї сторінки. Чи є спосіб визначити, які координати посилаються на батьківський елемент?

Редагувати:

Ось картинка того, що я намагаюся зробити: alt текст

Відповіді:


305

Одним із способів є використання offsetметоду jQuery для перекладу event.pageXта event.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
Так, це чудова ідея, якщо макет батьківського елемента не можна / не слід змінювати!
Pointy

2
Чи враховує ця відповідь прокладки / межі?
LeeGee

10
Згідно з документами, зсув не враховує "межі, поля чи накладки, встановлені на елементі тіла". Я не стикався з проблемою з моєю опублікованою відповіддю у використанні, але, можливо, було б добре перевірити, чи не встановлені.
джебл

2
Це не повинно працювати. offset()відносно теж, тому якщо батько є дитиною іншого елемента, це дасть неправильний результат. Використовуйте position()замість цього.
Flash Thunder

1
@FlashThunder offset () не є відносним, принаймні, не згідно з документами. Крім того, слід застосовувати стандартну практику, щоб на корпусі не було жодних запасів або прокладок.
Джеймс Уоткінс

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;Але ваша відповідь привела мене до правильного шляху.
Соломон Клоссон

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
Блискуче покращення врятувало мені день.
Буд Дамянов

майже, додайте маржу до полотна, і ви відійдете від поля
Бенн

Це якийсь чудовий фрагмент кодексу, велике спасибі!
Стефан

7

Це рішення підтримує всі основні браузери, включаючи IE. Він також дбає про прокручування. По-перше, це ефективно отримує положення елемента щодо сторінки та без використання рекурсивної функції. Потім він отримує х і у клацання миші відносно сторінки і робить віднімання, щоб отримати відповідь, яка є позицією відносно елемента (елемент може бути зображенням або поділом, наприклад):

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

@DutrowLLC, Pointy пропонує змінити стиль батьківського елемента "position:relative". Потім позиція jQuery повідомляє про свої позиції відносно батьківського елемента, а не сторінки. Формулювання моєї відповіді є поганим, це означає, що воно безпосередньо пов'язане з рішенням Pointy, але це спосіб розрахунку зміщення, коли ви не можете чи не хочете залежати від атрибутів стилю батьківського елемента.
jball

Отже, якщо я встановив "позиція: відносна", jQuery буде правильно повідомляти про положення відношення у всіх браузерах? Причина, про яку я запитую, полягає в тому, що документація jQuery, здавалося, означає, що єдине надійне положення миші у всіх браузерах було те, що стосується самого вікна браузера.
Кріс Дутроу

У вікні "позиція: відносний" буде встановлено параметр "верхній" та "лівий" (тощо) для дочірніх скриньок відносно прямокутника вмісту відносного батьківського поля.
Pointy

Можливо, я щось роблю неправильно, але це, здається, не працює у firefox. У мене "позиція: відносна;" встановлений у батьківській програмі, firefox повідомляє event.pageX та event.clientX однаково (щодо верхньої, лівої частини сторінки) та повідомляє event.offsetX як невизначений
Chris Dutrow

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>


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.