Событие Mouseenter и mouseleave с событием прокрутки окна

#javascript #jquery

Вопрос:

Я хочу измерить время, в течение которого курсор мыши находится в определенной области (div-контейнер). См. Код ниже.

До сих пор время выхода и входа (время наведения) измерялось только тогда, когда курсор мыши входил и выходил из соответствующего контейнера (из-за события mouseleave и mouseenter), но не тогда, когда пользователь использует колесо мыши или прокручивает окно. Моя цель состоит в том, чтобы изменить код таким образом, чтобы время наведения также измерялось при прокрутке окна (например, пользователь использует колесо мыши).

Я уже пытался реализовать событие .scroll() с помощью селектора «документ».

Кто-нибудь уже сталкивался с такой же проблемой и у кого есть решение этой проблемы?

 var hover_events = {};
var enter_time;
var leave_time;


$(".element").on('mouseenter', function(d) {
  enter_time = Date.now();
  hover_events[d.target.id] = {
    element_id: d.target.id,
    enter_time: enter_time,
    leave_time: undefined,
  };

});

$(".element").on('mouseleave', function(d) {
  leave_time = Date.now();
  hover_events[d.target.id]["leave_time"] = leave_time;

  console.log(hover_events[d.target.id])
  delete(hover_events[d.target.id]);

}); 
 .element {
  margin: 100px;
  width: 100px;
  height: 100px;
  background-color: lightblue;
}

#scroll {
  width: 1000px;
  height: 1000px;
} 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="scroll">
  <div class="element" id="test">
  </div>
</div> 

Комментарии:

1. курсор мыши в области, когда окно прокручивается — вы имеете в виду, что если окно прокрутилось, то вы хотите измерить время наведения? или вы имеете в виду измерение расстояния прокрутки окна при наведении курсора?

2. Я отредактировал свой вопрос. Я имею в виду, что я хочу измерить время наведения, даже если окно прокручивается.

3. Наверное, я не понимаю, что сейчас не работает в вашем коде

4. mouseleave и mouseenter работают только при перемещении курсора мыши. В случае, если вы не перемещаете мышь, это означает, что курсор мыши остается в точно таком же положении, то код не оценивает время входа или выхода. В простом примере это не вызывает большого беспокойства. Однако в реальном проекте я реализовал несколько направлений. Поэтому, если кто-то прокручивает страницу (например, использует колесо мыши), Я не могу измерить время зависания.

5. Мне кажется, я понял вашу задачу. Необходимо, чтобы события мыши запускались при прокрутке окна, в тот момент, когда курсор мыши попадает в светло-голубое поле. Я прав?

Ответ №1:

Я нашел этот вопрос интересным для работы… И потратьте на это немало времени.

Вот как я об этом подумал:

  • Используется mouseenter для записи time_enter .
  • используйте mouseleave для вычисления a time_spent для элемента и очистите time_enter .
  • Вкл mousemove ., запишите положение мыши x/y.
  • Включите scroll для всех элементов, получите позиции (относительно порта просмотра), сравните их с записанным положением мыши, чтобы вызвать a mouseenter или a mouseleave на нем.

Кодовый набор

 console.clear();

var elements = {};
let mouse_pos = {};

// Save all element position relative to the viewport
function positions() {
  $(".element").each(function () {
    let bounding_rect = this.getBoundingClientRect();
    elements[this.id] = elements[this.id] || {};

    elements[this.id].top = bounding_rect.top;
    elements[this.id].right = bounding_rect.right;
    elements[this.id].bottom = bounding_rect.bottom;
    elements[this.id].left = bounding_rect.left;
    elements[this.id].time_spent = elements[this.id].time_spent || 0;
  });
}

// Run once on load
positions();
let keys = Object.keys(elements);

$(window).on("scroll", function () {
  positions();

  // loop all elements
  keys.forEach(function (id) {
    let item = elements[id];

    if (
      mouse_pos.x > item.left amp;amp;
      mouse_pos.x < item.right amp;amp;
      mouse_pos.y > item.top amp;amp;
      mouse_pos.y < item.bottom
    ) {
      console.log("Hovering", id);
      $(`#${id}`).trigger("mouseenter");
    } else {
      $(`#${id}`).trigger("mouseleave");
    }
  });
});

$(document).on("mousemove", function (e) {
  mouse_pos.x = e.pageX;
  mouse_pos.y = e.pageY;
  //console.log(mouse_pos)
});

$(".element").on("mouseenter", function (e) {
  elements[e.target.id].time_enter = Date.now();
  //console.log(elements);
  $(`#${e.target.id}`).addClass("hovered");
});

$(".element").on("mouseleave", function (e) {
  if (elements[e.target.id].time_enter) {
    elements[e.target.id].time_spent  =
      Date.now() - elements[e.target.id].time_enter;
    delete elements[e.target.id].time_enter;
    //console.log(elements);

    $(`#${e.target.id}`)
      .text((elements[e.target.id].time_spent / 1000).toFixed(2)   " sec.")
      .removeClass("hovered");
  }
}); 
 body {
  height: 1000px;
}

.row {
  display: flex;
  justify-content: space-between;
  margin-top: 100px;
}

.element {
  width: 100px;
  height: 100px;
  background-color: lightblue;
  display: flex;
  justify-content: center;
  align-items: center;
}

.hovered {
  border: 1px solid red;
} 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="row">
  <div class="element" id="el_1"></div>
  <div class="element" id="el_2"></div>
  <div class="element" id="el_3"></div>
  <div class="element" id="el_4"></div>
</div>
<div class="row">
  <div class="element" id="el_5"></div>
  <div class="element" id="el_6"></div>
  <div class="element" id="el_7"></div>
  <div class="element" id="el_8"></div>
</div>