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
andscreenY
return
the screen coordinates (the origin is the top-left corner of user's monitor)clientX
andclientY
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 viewportthis.getBoundingClientRect().left
is
the position of the element relative to the document viewportthis.clientLeft
is
the amount of border (and scrollbar) between the element boundary and the inner coordinatesthis.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?的更多相关文章
- Why AlloyFinger is so much smaller than hammerjs?
AlloyFinger is the mobile web gesture solution at present inside my company, major projects are in u ...
- OpenSceneGraph控制模型
OpenSceneGraph控制模型 转自:http://www.cppblog.com/eryar/archive/2012/05/28/176538.html 一.简介 对模型的控制就是修改模型的 ...
- 【RobotFramework】Selenium2Library类库关键字使用说明
Add CookieArguments:[ name | value | path=None | domain=None | secure=None | expiry=None ]Adds a coo ...
- pageX/Y, offset(), position(), scrollTop(), screenX/Y, clientX/Y, pageX/Y
event.pageX get mouse position Description: The mouse position relative to the left edge of the docu ...
- cocos2d中的可见性检测
游戏的在进行一次渲染的时候,通常会提交大量的渲染对象给gpu.在这些需要渲染的对象中,并不是所有对象都会出现镜头中,即有一部分对象是不可见的. 通常有两种方式来完成不可见对象的剔除工作: (1)直接交 ...
- js 导出Excel
最近从Silverlight这边转到javascript过来,现在要导出一个导出excel的功能.上级领导指示当页显示多少数据,就导出多少数据,没有必要从后台在去数据.以前也没有接触过这方面的,在网上 ...
- Easy Multiple Copy to Clipboard by ZeroClipboard
要实现在多个复制按钮复制的功能(具体代码在附件中,路径修改一下就行了): <%@ page language="java" import="java.util.*& ...
- 转:VS2008 vs2010中JQUERY智能提醒
第一步: 安装VS 2008 SP1 VS 2008 SP1 在Visual Studio中加了更丰富的JavaScript intellisense支持,对很大部分的JavaScript库加了代码完 ...
- appium点击屏幕(手势)
在android测试过程中,会遇到要点击一下屏幕的需求. 在appium旧版本使用下面代码点击android屏幕,没有报错.Map tap = new HashMap(); tap.put(" ...
随机推荐
- winform显示系统托盘,双击图片图表显示窗体,退出窗体是否提示
private void Form1_FormClosing(object sender, FormClosingEventArgs e) { DialogResult result = Messag ...
- Linux网络驱动程序
Linux 的网络系统主要是基于 BSD UNIX 的套接字机制. 在系统与驱动程序之间定义了数据结构 sk_buff 进行传输数据.系统支持对发送数据和接收数据缓存,提供流控机制并提供对多协议的支持 ...
- HDU 5672 String 尺取法追赶法
String Problem Description There is a string S.S only contain lower case English character.(10≤lengt ...
- 使用sed -i对文本字符串进行增删改查
sed是一个很好的文件处理工具,本身是一个管道命令,主要以行为单位进行处理,可以将数据行进行替换.删除.新增.选取等特定工作.1. sed命令行格式sed [选项] [命令] 1.1 选项-n,使用安 ...
- ROS-Rviz-turtlebot3仿真信息查看
前言:Rviz是ROS自带的一种3D可视化工具. 一.安装turtlebot3功能包 1.1 安装依赖包 sudo apt-get install ros-kinetic-joy ros-kineti ...
- IP地址转化为数字,charindex ,SUBSTRING
SET NOCOUNT ON; declare @I_PCity table ( IPStart nvarchar(), Area nvarchar(), CityID int, IPID int ) ...
- Android Handler学习笔记
已经习惯了挖坑不填,继续任性一下,周一到周五继续挖坑,每周六周日负责填坑. 1.从Android UI线程谈起 出于性能考虑,Android 中的UI操作并不是线程安全的,所以Android中规定只能 ...
- What is the difference between arguments and parameters?
What is the difference between arguments and parameters? Parameters are defined by the names that ap ...
- Android 7.0 Gallery图库源码分析4 - SlotView手势监听及页面跳转
上篇文章讲了初始化View时会实例化一个SlotView并监听其事件,至于它是怎么实现的,用的是Android自带的GestureDetector. GestureDetector是Android自带 ...
- jq——DOM文档处理
内部插入:父子级关系 1 $(a).append($(b))把b插入到a里面(a里面的面后) $("div").append($("<p>段落</p&g ...