zl程序教程

您现在的位置是:首页 >  前端

当前栏目

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

css3 for to The get an How has
2023-09-14 08:57:15 时间
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 dont know how to fix it.

Im not using any JavaScript library, and I want to understand how things work in plain JavaScript. So, please, dont 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.


screenX and screenY return the screen coordinates (the origin is the top-left corner of users 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


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" 

 div /div 

 div /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 doesnt know about the transformations, and thus calculates a wrong position. Whats 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.


第101天:CSS3中transform-style和perspective 一、transform-style 1、transform-style属性是3D空间一个重要属性,指定嵌套元素如何在3D空间中呈现。 有两个属性值:flat和preserve-3d。 transform-style属性的使用语法非常简单: transform-style: flat | preserve-3d 其中flat值为默认值,表示所有子元素在2D平面呈现。