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

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.

时间: 2024-09-28 16:17:53

How to get the MouseEvent coordinates for an element that has CSS3 Transform?的相关文章

difference of top and left between Javascript and Jquery

1, top and left relative to the document jquery .offset() Get the current coordinates of the first element, or set the coordinates of every element, in the set of matched elements, relative to the document. var top = $('#elementID').offset().top; var

ShareObject 数据存储

ShareObject,顾名思义共享对象,而通常意义上的共享,从B/S结构上来讲,无非是客户端(浏览器端)的共享和服务器端的共享了,不错,ShareObject刚好份演了这两种角色.而且ShareObject也是按此进行了两种分类,一类是LSO--Local Share Object(本地共享对象)其实类似于cookie,而另一种RSO--Remote Share Object(远程共享对象) 我感觉比较类似于JSP中的Application对象,但好象比Application更强大 一:LSO

Page Scroll using Selenium WebDriver

Using JavaScript Scroll Down: import org.openqa.selenium.JavascriptExecutor;WebDriver driver = new FirefoxDriver();JavascriptExecutor jse = (JavascriptExecutor)driver;jse.executeScript("scroll(0, 250)"); //y value '250' can be altered Scroll up:

zclip 复制内容到剪切板

直接上代码 </pre><pre code_snippet_id="411566" snippet_file_name="blog_20140630_3_1654861" name="code" class="html"><!DOCTYPE html> <html> <head> <title>ZeroClipboard Test</title>

js 完美兼容浏览器的复制功能

1,js结合swf的复制功能,完美兼容火狐,谷歌,360,ie8,使用示例:(ps:引入copy.swf比较重要,文件传送门 解压密码:http://www.bieanju.com/,为了防止360删除文件请解压后去除后缀的1) function copyText(){        var clip = new ZeroClipboard.Client();         clip.setHandCursor(true);                //var text= documen

WinPhone学习笔记(四)——磁贴

对每个Windows Phone的使用者来说,给他们的第一印象就是大大小小的磁贴——Metro,本篇介绍的是Windows Phone的磁贴,提到的有开始菜单的磁贴,也有在App里面的磁贴. 开始菜单的磁贴 首先介绍了一下每个磁贴的构造,每个磁贴分正反两面,正反两面都有图标,而正面有一个标题和统计数量(一般用作消息推送的时候用),在背面就有一个描述性的内容,下图就摘自MSDN上的图片,图中黑色字体其实就是每个磁贴数据类的属性,这个稍后会提到 对于一个磁贴来说,他的图片像素建议是173*173像素

Automating mobile gestures

While the Selenium WebDriver spec has support for certain kinds of mobile interaction, its parameters are not always easily mappable to the functionality that the underlying device automation (like UIAutomation in the case of iOS) provides. To that e

appium()-java-client-api

//appium java-client-api 介绍 原文地址:http://appium.github.io/java-client/index-all.html#_S_ A B C D E F G H I J K L M N O P Q R S T U V W Y Z A AccessibilityId(String) - Static method in class io.appium.java_client.MobileBy About Android accessibility ht

Flex开发简单工作流程设计工具

在线预览地址 http://rj.8634.com/xiaoshandong/workflowdesigner/workflowdesigner.html 源代码下载   http://files.cnblogs.com/files/ffmpeg/WorkFlowDesigner.zip 截图   源代码 WorkFlowDesigner.mxml <?xml version="1.0" encoding="utf-8"?> <mx:Applica