如何获取具有CSS3变换的元素的MouseEvent坐标? [英] How to get the MouseEvent coordinates for an element that has CSS3 Transform?

查看:357
本文介绍了如何获取具有CSS3变换的元素的MouseEvent坐标?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想检测其中> c 在与所点击的元素相关的<为什么?因为我想在点击的位置添加一个绝对定位的子元素。



我知道当没有CSS3转换存在时,如何检测它(见下面的描述)。但是,当我添加一个CSS3 Transform,那么我的算法会中断,我不知道如何修复它。



我不使用任何JavaScript库,我想了解事情如何在纯JavaScript中工作。所以,请不要回答只是使用jQuery。



顺便说一下,我想要的解决方案,所有MouseEvents,而不只是点击。不是那么重要,因为我相信所有鼠标事件共享相同的属性,因此相同的解决方案应该适用于所有这些。






背景资讯



根据 DOM Level 2 specification ,a MouseEvent 具有与获取事件坐标相关的几个属性:




  • screenX screenY 返回屏幕坐标用户监视器的左角)

  • clientX clientY c code


    $ b

    因此,为了找到 MouseEvent 相对于点击的元素内容,我必须这样做:

      ev.clientX  -  this.getBoundingClientRect this.clientLeft + this.scrollLeft 




    • ev .clientX 是相对于文档视口的坐标

    • this.getBoundingClientRect()。left 元素相对于文档视口的位置

    • this.clientLeft 是元素边界和内部坐标

    • this.scrollLeft 是元素内滚动的数量



    getBoundingClientRect() clientLeft scrollLeft CSSOM查看模块中指定



    没有CSS转换的实验(可运作)



    令人困惑? 尝试以下JavaScript和HTML 。点击后,会在点击发生的位置显示一个红点。这个版本是很简单,并按预期工作。

      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 =experimentstyle =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>



    试验添加CSS变换(失败)



    现在,尝试添加CSS transform

      #experiment {
    transform:scale(0.5);
    -moz-transform:scale(0.5);
    -o-transform:scale(0.5);
    -webkit-transform:scale(0.5);
    / *请注意,这是一个非常简单的转换。 * /
    / *记得还要考虑更复杂的,如下所述。 * /
    }

    算法不知道转换,错位。另外,Firefox 3.6和Chrome 12之间的结果不同。Opera 11.50的行为与Chrome一样。



    在这个例子中,唯一的转换是缩放,所以我可以乘缩放因子来计算正确的坐标。然而,如果我们考虑任意变换(缩放,旋转,倾斜,平移,矩阵),甚至嵌套变换(一个变换的元素在另一个变换的元素),那么我们真的需要一个更好的方法来计算坐标。

    解决方案

    您遇到的行为是正确的,您的算法没有打破。首先,CSS3转换的设计不会干扰盒子模型。



    尝试解释...



    当您对元素应用CSS3变换。元素假定一种相对定位。因为周围的元素不受转换的元素影响。



    例如。想象三个div在一个水平行。如果应用缩放变换以减小中心div的大小。周围的div不会向内移动,占据曾经占据过变换元素的空间。



    示例: http://jsfiddle.net/AshMokhberi / bWwkC /



    因此在框模型中,元素实际上并不改变大小。



    您还必须记住,您正在应用比例变换,因此您的元素实际大小实际上与其原始大小相同尺寸。



    假设你创建一个宽度为div的div,的1000px,并缩小到1/2的大小。 div的内部大小仍为1000像素,而不是500像素。



    因此,相对于div的真实大小,点的位置是正确的。



    示例来说明。



    说明


    1. 点击div并将鼠标放在相同的位置。

    2. 查找错误位置的点。

    3. 按Q,div将变为正确的大小。

    4. 移动鼠标,在正确位置找到要点击的位置。

    http://jsfiddle.net/AshMokhberi/EwQLX/



    为了使鼠标点击坐标匹配div上的可见位置,您需要了解鼠标是基于窗口返回坐标,您的div偏移也基于其真实大小。



    由于你的对象大小相对于窗口,唯一的解决方案是使用与div相同的缩放值缩放偏移坐标。



    但是,这可能变得棘手基于您设置您的div的Transform-origin属性。因为这将影响补偿。



    请参阅此处。



    http://jsfiddle.net/AshMokhberi/KmDxj/



    希望这有助于。


    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.

    解决方案

    The behaviour you are experiencing is correct, and your algorithm isn't breaking. Firstly CSS3 Transforms are designed not to interfere with the box model.

    To try and explain...

    When you apply a CSS3 Transform on an element. the Element assumes a kind of relative positioning. In that the surrounding elements are not effected by the transformed element.

    e.g. imagine three div's in a horizontal row. If you apply a scale transform to decrease the size of the centre div. The surrounding div's will not move inwards to occupy the space that was once occupied the transformed element.

    example: http://jsfiddle.net/AshMokhberi/bWwkC/

    So in the box model, the element does not actually change size. Only it's rendered size changes.

    You also have to keep in mind that you are applying a scale Transform, so your elements "real" size is actually the same as it's original size. You are only changing it's perceived size.

    To explain..

    Imagine you create a div with a width of 1000px and scale it down to 1/2 the size. The internal size of the div is still 1000px, not 500px.

    So the position of your dots are correct relative to the div's "real" size.

    I modified your example to illustrate.

    Instructions

    1. Click the div and keep you mouse in the same position.
    2. Find the dot in the wrong position.
    3. Press Q, the div will become the correct size.
    4. Move your mouse to find the dot in the correct position to where you clicked.

    http://jsfiddle.net/AshMokhberi/EwQLX/

    So in order to make the mouse clicks co-ordinates match the visible location on the div, you need to understand that the mouse is giving back co-ordinates based on the window, and your div offsets are also based on its "real" size.

    As your object size is relative to the window the only solution is to scale the offset co-ordinates by the same scale value as your div.

    However this can get tricky based on where you set the Transform-origin property of your div. As that is going to effect the offsets.

    See here.

    http://jsfiddle.net/AshMokhberi/KmDxj/

    Hope this helps.

    这篇关于如何获取具有CSS3变换的元素的MouseEvent坐标?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆