How to get the MouseEvent coordinates for an element that has CSS3 Transform?
2017-06-18 13:15
465 查看
I want to detect where a
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.
According to DOM
Level 2 specification, a
few properties related to getting the event coordinates:
the screen coordinates (the origin is the top-left corner of user's monitor)
the coordinates relative the document viewport.
Thus, in order to find the position of the
to the clicked element content, I must do this math:
the coordinate relative to the document viewport
the position of the element relative to the document viewport
the amount of border (and scrollbar) between the element boundary and the inner coordinates
the amount of scrolling inside the element
specified at CSSOM
View Module.
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.
Now, try adding a CSS
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.
MouseEventhas
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 DOMLevel 2 specification, a
MouseEventhas
few properties related to getting the event coordinates:
screenXand
screenYreturn
the screen coordinates (the origin is the top-left corner of user's monitor)
clientXand
clientYreturn
the coordinates relative the document viewport.
Thus, in order to find the position of the
MouseEventrelative
to the clicked element content, I must do this math:
ev.clientX - this.getBoundingClientRect().left - this.clientLeft + this.scrollLeft
ev.clientXis
the coordinate relative to the document viewport
this.getBoundingClientRect().leftis
the position of the element relative to the document viewport
this.clientLeftis
the amount of border (and scrollbar) between the element boundary and the inner coordinates
this.scrollLeftis
the amount of scrolling inside the element
getBoundingClientRect(),
clientLeftand
scrollLeftare
specified at CSSOM
View Module.
Experiment without CSS Transform (it works)
Confusing? Try the following pieceof 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?
- How to get the MouseEvent coordinates for an element that has CSS3 Transform?
- How to get the RGB values for a pixel on an image on the iphone
- How to restore an element that has been deleted in CCRC?
- How to get the xpath by clicking an html element
- Here's an example that shows how to enumerate through the features of a selection set, returning the value of each field in the attribute table except for the geometry colum.
- how to know whether an element has an class
- Question 30: What is the order of destructor calls for an object of class Y inherited from class X that has an object of class A
- HowTO: Create an Event Log Source in code, without the Permission errors
- An error has occured on the server. For details please check the Event (Application) log on the web server.
- How to prepare a workstation for imaging that includes the NS Agent
- You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
- How can selenium web driver get to know when the new window has opened and then resume its execution
- From an inner class, "this" points to the inner object. How do I get a "this" pointer to the enclosing object?
- The parameter is (or has an element that is) the wrong kind of geometry
- how to scroll a ScrollViewer at design time in Blend to manually design content for it that goes beyond the visible view
- java.sql.SQLException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for
- How to write an application that supports the Fast User Switching feature by using Visual Basic .NET or Visual Basic
- How to use the date format that has been setup as default in Settings?
- uiview 某点返回 色值 How to get the color of a pixel in an UIView?