【问题标题】:Get actual pixel coordinates of div after CSS3 transformCSS3变换后获取div的实际像素坐标
【发布时间】:2013-06-09 20:50:51
【问题描述】:

是否可以获得<div /> 的四个实际角坐标,该坐标已使用scaleskewrotate 等CSS3 属性进行转换?

示例:

在 CSS3 转换之前的坐标是

x1y1: 0,0
x1y2: 0,200
x2y1: 200,0
x2yw: 200,200

div 看起来像这样:

经过一点 CSS3 魔术transform: skew(10deg, 30deg) rotate(30deg) scale(1, 2); 它看起来像这样:

如何获取实际角(不是边界框)的坐标(使用 javascript)? 非常感谢任何帮助。

【问题讨论】:

  • 大体上可以肯定,目前还没有 API。请记住,CSS 转换在渲染区域中运行,而 JS 在 ECMA/DOM 区域中运行。虽然这会是一个很好的上瘾。
  • @FabrícioMatté 我想我可以从属性中计算它们——我的数学朋友在哪里:)?
  • 没错,我之前见过几个类似的问题,我的评论是应用数学。 ;) 虽然我相信每个人都希望获得一个 API 或 hack,以懒惰的方式为我们提供正确的数字。 :P
  • 绝妙的解决方案!我在数学上绞尽脑汁太久了。这很好很简单。

标签: javascript jquery css transform


【解决方案1】:

您可以使用 .getBoundingClientRect() 找到元素相对于窗口的新位置

【讨论】:

    【解决方案2】:

    经过数小时尝试计算所有变换并几乎绝望地放弃后,我想出了一个简单而天才的小技巧,它非常容易获得变换后<div />的角点

    我刚刚在 div 内添加了四个手柄,它们位于角落但不可见:

    <div id="div">
      <div class="handle nw"></div>
      <div class="handle ne"></div>
      <div class="handle se"></div>
      <div class="handle sw"></div>
    </div>
    

    .handle {
        background: none;
        height: 0px;
        position: absolute;
        width: 0px;
    }   
    .handle.nw {
        left: 0;
        top: 0;
    }   
    .handle.ne {
        right: 0;
        top: 0;
    }   
    .handle.se {
        right: 0;
        bottom: 0;
    }       
    .handle.sw {
        left: 0;
        bottom: 0;
    }           
    

    现在使用 jQuery(或纯 js)检索位置是小菜一碟:

    $(".handle.se").offset()
    

    【讨论】:

    • 哈!杰出的。我花了几个小时试图对此进行数学计算。终于放弃了,看向了SO。您的回答简单而富有创意。
    • 只是想补充一点,我目前正在使用这种技术,而且效果很好!如果浏览器会为你做,为什么还要自己做呢!
    • 注意:不适用于任意元素。仅适用于样式位置明确设置为相对或绝对的转换元素。否则,您的“句柄”最终可能会呈现在其父元素的范围之外。
    • @user2782001 你可以使用各种方法来确保每个元素都在角落(即一个 0x0 容器,然后是 0x0 与宽度高度的左边距或边距顶部 0x0>0x0> 等...基本上,您可以使用margin 偏移角落,但您在额外的 0x0 div 中包含角点。
    【解决方案3】:

    我向您推荐这个网站:http://www.useragentman.com/blog/2011/01/07/css3-matrix-transform-for-the-mathematically-challenged/,尤其是“关于矩阵的其他有趣事实”部分...

    但正如 Egor Nepomnyaschih 指出的那样,您只需为每个转换实现微积分并将它们链接起来。

    我已经根据您的示例实现了一个 jsFiddle:http://jsfiddle.net/pvS8X/3/

    请注意:原点是您的图形的中间!如果你想引用左上角,你必须设置这是你的 CSS 代码:

    transform-origin: 0 0;
    

    参见。 https://developer.mozilla.org/fr/docs/CSS/transform-origin.

    主要的方法是这些:

    function skew(p, alpha, beta) {
        var tan_a = Math.tan(alpha * Math.PI / 180),
            tan_b = Math.tan(beta * Math.PI / 180),
            p_skewed = {};
    
        p_skewed.x = p.x + p.y * tan_a;
        p_skewed.y = p.x * tan_b + p.y;
    
        return p_skewed;
    }
    
    
    function rotate(p, theta) {
        var sin_th = Math.sin(theta * Math.PI / 180),
            cos_th = Math.cos(theta * Math.PI / 180),
            p_rot = {};
    
        p_rot.x = p.x * cos_th - p.y * sin_th;
        p_rot.y = p.x * sin_th + p.y * cos_th;
    
        return p_rot;
    }
    
    
    function scale(p, sx, sy) {
        var p_scaled = {};
    
        p_scaled.x = p.x * sx;
        p_scaled.y = p.y * sy;
    
        return p_scaled;
    }
    

    其中 p 是 { x: &lt;some_horizontal_pos&gt;, y: &lt;some_vertical_pos&gt;} 形式的对象。

    【讨论】:

    • 我还不太明白。这究竟返回了什么?我怎样才能找回其他 3 个角?
    • @Horen 您只需将值放在 2 个字段 x 和 y 中,您就会看到相应的输出...我已经更新了我的小提琴,以便取相对于左上角的坐标中间:jsfiddle.net/pvS8X/7.
    • 是否可以添加 3d css 变换(rotateX/Y 和透视)?
    • 第一个链接正是我所需要的。谢谢!
    【解决方案4】:

    我认为没有相应的 API。以及在 HTML5 &lt;canvas&gt; 中没有转换坐标的 API。但是有一种方法可以手动计算坐标。这是我的 &lt;canvas&gt; 库中的一个转换坐标的类:https://github.com/enepomnyaschih/jwcanvas/blob/master/jwidget/public/jwcanvas/transform.js

    您可以将其用作模板。

    要初始化坐标系,你应该只实例化一个JW.Canvas.Transform类的对象并应用方法complex。之后,您可以通过transform 方法将其他变换应用于坐标系。矩阵是:

    • 翻译:[1, 0, 0, 1, x, y]
    • 比例:[x, 0, 0, y, 0, 0]
    • 顺时针旋转:[cos(a), sin(a), -sin(a), cos(a), 0, 0]
    • 沿 x 倾斜:[1, 0, tan(a), 1, 0, 0]
    • 沿 y 倾斜:[1, tan(a), 0, 1, 0, 0]

    之后,您将能够通过convert 方法转换坐标。使用back方法计算反向转换对象。

    【讨论】:

    • 它是否适用于 CSS3 transform3D 矩阵(rotateX、rotateY 和透视)?
    • 在 3D 中,使用 4x4 矩阵来表示变换,因此正交变换将有 12 个含义数字,而不是 6 个,最后一行固定为:[0, 0, 0, 1]。平移、缩放、旋转和倾斜变换将具有相似的矩阵。快速谷歌搜索有助于找到透视投影的矩阵:[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 1/d , 1]](最后一行是意思!)
    • 感谢您的回答!
    猜你喜欢
    • 2011-10-10
    • 2015-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-22
    • 2014-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多