How to get the MouseEvent coordinates for an element that has CSS3 Transform?

來源:互聯網
上載者:User

標籤:net   specified   mono   developer   lib   normal   jquery   algorithm   module   

I want to detect where a MouseEvent has occurred, in coordinates relative to the clicked element. Why? Because I want to add an absolutely positioned child element at the clicked location.

I know how to detect it when no CSS3 transformations exist (see description below). However, when I add a CSS3 Transform, then my algorithm breaks, and I don‘t know how to fix it.

I‘m not using any JavaScript library, and I want to understand how things work in plain JavaScript. So, please, don‘t answer with "just use jQuery".

By the way, I want a solution that works for all MouseEvents, not just "click". Not that it matters, because I believe all mouse events share the same properties, thus the same solution should work for all of them.

Background information

According to DOM Level 2 specification, a MouseEvent has few properties related to getting the event coordinates:

  • screenX and screenY return the screen coordinates (the origin is the top-left corner of user‘s monitor)
  • clientX and clientY return the coordinates relative the document viewport.

Thus, in order to find the position of the MouseEvent relative to the clicked element content, I must do this math:

ev.clientX - this.getBoundingClientRect().left - this.clientLeft + this.scrollLeft
  • ev.clientX is the coordinate relative to the document viewport
  • this.getBoundingClientRect().left is the position of the element relative to the document viewport
  • this.clientLeft is the amount of border (and scrollbar) between the element boundary and the inner coordinates
  • this.scrollLeft is the amount of scrolling inside the element

getBoundingClientRect()clientLeft and scrollLeft are specified at CSSOM View Module.

Experiment without CSS Transform (it works)

Confusing? Try the following piece of JavaScript and HTML. Upon clicking, a red dot should appear exactly where the click has happened. This version is "quite simple" and works as expected.

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>
Experiment adding a CSS Transform (it fails)

Now, try adding a 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. */}

The algorithm doesn‘t know about the transformations, and thus calculates a wrong position. What‘s more, the results are different between Firefox 3.6 and Chrome 12. Opera 11.50 behaves just like Chrome.

In this example, the only transformation was scaling, so I could multiply the scaling factor to calculate the correct coordinate. However, if we think about arbitrary transformations (scale, rotate, skew, translate, matrix), and even nested transformations (a transformed element inside another transformed element), then we really need a better way to calculate the coordinates.

How to get the MouseEvent coordinates for an element that has CSS3 Transform?

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.