Выбрать главу

Если два щелка происходят достаточно быстро друг за другом, запускается событие "dblclick" (double-click), сразу после второго запуска "click".

Для получения точных координат места, где произошло событие мыши, обратитесь к свойствам pageX и pageY – они содержат координаты в пикселях относительно верхнего левого угла.

В примере создана примитивная программа для рисования. Каждый раз по клику на документе он добавляет точку под вашим курсором. В главе 19 будет представлена менее примитивная программа для рисования.

<style>

  body {

    height: 200px;

    background: beige;

  }

  .dot {

    height: 8px; width: 8px;

    border-radius: 4px; /* скруглённые углы */

    background: blue;

    position: absolute;

  }

</style>

<script>

  addEventListener("click", function(event) {

    var dot = document.createElement("div");

    dot.className = "dot";

    dot.style.left = (event.pageX - 4) + "px";

    dot.style.top = (event.pageY - 4) + "px";

    document.body.appendChild(dot);

  });

</script>

Свойства clientX и clientY похожи на pageX и pageY, но дают координаты относительно части документа, которая видна сейчас (если документ был прокручен). Это удобно при сравнении координат мыши с координатами, которые возвращает getBoundingClientRect – его возврат тоже связан с относительными координатами видимой части документа.

Движение мыши

Каждый раз при сдвиге курсора мыши запускается событие "mousemove". Его можно использовать для отслеживания позиции мыши. Обычно это нужно при создании некоей функциональности, связанной с перетаскиванием объектов мышью.

К примеру, следующая программа отображает полоску и устанавливает обработку событий так, что движение влево и вправо уменьшает или увеличивает её ширину.

<p>Переместите мышь для увеличения ширины:</p>

<div style="background: orange; width: 60px; height: 20px">

</div>

<script>

  var lastX; // Последняя позиция мыши

  var rect = document.querySelector("div");

  rect.addEventListener("mousedown", function(event) {

    if (event.which == 1) {

      lastX = event.pageX;

      addEventListener("mousemove", moved);

      event.preventDefault(); // Запретим выделение

    }

  });

  function moved(event) {

    if (event.which != 1) {

      removeEventListener("mousemove", moved);

    } else {

      var dist = event.pageX - lastX;

      var newWidth = Math.max(10, rect.offsetWidth + dist);

      rect.style.width = newWidth + "px";

      lastX = event.pageX;

    }

  }

</script>

Обратите внимание – обработчик "mousemove" зарегистрирован у всего окна. Даже если мышь уходит за пределы полоски, нам надо обновлять её размер и прекращать это, когда кнопку отпускают.

Когда курсор попадает на узел и уходит с него, происходят события "mouseover" или "mouseout". Их можно использовать, кроме прочего, для создания эффектов проведения мыши, показывая или меняя стиль чего-либо, когда курсор находится над этим элементом.

К сожалению, создание такого эффекта не ограничивается запуском его при событии "mouseover" и завершением при событии "mouseout". При движении мыши от узла к его дочерним узлам на родительском узле происходит событие "mouseout", хотя мышь, вообще говоря, его и не покидала. Что ещё хуже, эти события распространяются как и все другие, поэтому вы всё равно получаете "mouseout" при уходе курсора с одного их дочерних узлов того узла, где вы зарегистрировали обработчик.

Для обхода проблемы можно использовать свойство relatedTarget объекта событий. Он сообщает, на каком узле была до этого мышь при возникновении события "mouseover", и на какой элемент она переходит при событии "mouseout". Нам надо менять эффект, только когда relatedTarget находится вне нашего целевого узла. Только в этом случае событие на самом деле представляет собой переход на наш узел (или уход с узла).

<p>Наведите мышь на этот <strong>параграф </strong>.</p>

<script>

  var para = document.querySelector("p");

  function isInside(node, target) {

    for (; node != null; node = node.parentNode)

      if (node == target) return true;

  }

  para.addEventListener("mouseover", function(event) {

    if (!isInside(event.relatedTarget, para))