Как получить координаты MouseEvent для элемента с CSS3 Transform? - PullRequest
45 голосов
/ 21 июля 2011

Я хочу определить , где a MouseEvent, в координатах относительно элемента, по которому щелкнули .Зачем?Потому что я хочу добавить абсолютно позиционированный дочерний элемент в выбранном месте.

Я знаю, как его обнаружить, когда нет преобразований CSS3 (см. Описание ниже).Однако, когда я добавляю CSS3 Transform, мой алгоритм ломается, и я не знаю, как это исправить.

Я не использую какую-либо библиотеку JavaScript, и я хочу понять, как все работает в простом видеJavaScript.Поэтому, пожалуйста, не отвечайте «просто используйте jQuery».

Кстати, я хочу решение, которое работает для всех MouseEvents, а не просто «щелкает».Это не имеет значения, потому что я считаю, что все события мыши имеют одинаковые свойства, поэтому для всех них должно работать одно и то же решение.


Справочная информация

Согласно DOMСпецификация уровня 2 , a MouseEvent имеет несколько свойств, связанных с получением координат события:

  • screenX и screenY возвращают координаты экрана (источникявляется верхним левым углом монитора пользователя)
  • clientX и clientY возвращают координаты относительно области просмотра документа.

Таким образом, чтобы найти положениеMouseEvent относительно содержимого элемента, по которому щелкнули, я должен сделать следующее:

ev.clientX - this.getBoundingClientRect().left - this.clientLeft + this.scrollLeft
  • ev.clientX - это координата относительно окна просмотра документа
  • this.getBoundingClientRect().left - этопозиция элемента относительно области просмотра документа
  • this.clientLeft - это величина границы (и полосы прокрутки) между границей элемента и внутренними координатами
  • this.scrollLeft - это величина прокрутки внутриэлемент

getBoundingClientRect(), clientLeft и scrollLeft указаны в CSSOM View Module .

Эксперимент без CSS Transform (работает)

Запутываетесь? Попробуйте следующий фрагмент JavaScript и HTML .При нажатии, красная точка должна появиться именно там, где произошел щелчок.Эта версия «довольно простая» и работает, как и ожидалось.

function click_handler(ev) {
    var rect = this.getBoundingClientRect();
    var left = ev.clientX - rect.left - this.clientLeft + this.scrollLeft;
    var top = ev.clientY - rect.top - this.clientTop + this.scrollTop;

    var dot = document.createElement('div');
    dot.setAttribute('style', 'position:absolute; width: 2px; height: 2px; top: '+top+'px; left: '+left+'px; background: red;');
    this.appendChild(dot);
}

document.getElementById("experiment").addEventListener('click', click_handler, false);

<div id="experiment" style="border: 5px inset #AAA; background: #CCC; height: 400px; position: relative; overflow: auto;">
    <div style="width: 900px; height: 2px;"></div> 
    <div style="height: 900px; width: 2px;"></div>
</div>

Эксперимент по добавлению CSS-преобразования (он не работает)

Теперь попробуйте добавить CSS transform:

#experiment {
    transform: scale(0.5);
    -moz-transform: scale(0.5);
    -o-transform: scale(0.5);
    -webkit-transform: scale(0.5);
    /* Note that this is a very simple transformation. */
    /* Remember to also think about more complex ones, as described below. */
}

Алгоритм не знает о преобразованиях и, таким образом, вычисляет неправильную позицию.Более того, результаты отличаются между Firefox 3.6 и Chrome 12. Opera 11.50 ведет себя так же, как Chrome.

В этом примере единственным преобразованием было масштабирование, поэтому я мог умножить коэффициент масштабирования для вычисления правильной координаты.Однако, если мы думаем о произвольных преобразованиях (масштабирование, поворот, наклон, преобразование, матрица) и даже о вложенных преобразованиях (преобразованный элемент внутри другого преобразованного элемента), то нам действительно нужен лучший способ для вычисления координат.

Ответы [ 11 ]

0 голосов
/ 05 сентября 2013

Работает нормально, относительное или абсолютное :) простое решение

var p = $( '.divName' );
var position = p.position();  
var left = (position.left  / 0.5);
var top =  (position.top  / 0.5);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...