【问题标题】:XY coordinates of rotated HTML elements corners旋转的 HTML 元素角的 XY 坐标
【发布时间】:2017-10-30 13:52:24
【问题描述】:

试图获取 HTML 元素的 XY 坐标,因此我可以计算旋转元素的角相对于另一个元素的物理距离(以像素为单位)。

在 sn-p 中,我尝试计算内部 div 的左上角到外部 div 中心的距离。但我只有非旋转 div 的 LeftTop 值。我需要这些值来反映旋转 div 的 XY 点。相对于视口或另一个元素,有什么方法可以得到这一点?

我尝试过getBoundingClientRect(),但它给出了更大的矩形和错误的坐标,因为它实际上是一个包含完整旋转 div 的垂直框。

那么,请问有什么方法可以得到这些坐标吗?

document.getElementById('outRotated').innerHTML = clacDistancCornerCenter() + "  Rotated distance of corner to center: "


function clacDistancCornerCenter() {
  var outer = document.getElementById('outer');
  var inner = document.getElementById('inner');

  var centerX = outer.offsetWidth / 2;
  var centerY = outer.offsetHeight / 2;


  var innersCornerX = outer.offsetLeft;
  var innersCornerY = outer.offsetTop;

  //distance formula -> d = sqrt( pow( x2 - x1)  + pow( y2 - y1) )

  var distance = Math.sqrt(Math.pow(centerX - innersCornerX, 2) + Math.pow(centerY - innersCornerY, 2));

  return distance;
}

function calcDistHorizontal() {
  $('div').css('transform', 'rotate(0deg)');
  document.getElementById('outHorizontal').innerHTML = clacDistancCornerCenter()+ "  This Should be differnt when horizontal: ";
}
div {
  top: 15%;
  left: 20%;
  width: 50%;
  height: 50%;
  border: 1px solid black;
  position: absolute;
  display: block;
  transform: rotate(25deg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="outRotated"> </p>
<p id="outHorizontal"> </p>

<button onclick="calcDistHorizontal()">Distance Horizontal</button>

<div id="outer">
  <div id="mid">
    <div id="inner">
    </div>
  </div>
</div>

【问题讨论】:

  • 不确定是否有直接的方法。但是如果你知道非旋转坐标、旋转角度和旋转原点,你可以用一些数学方法手动计算。

标签: javascript jquery html css math


【解决方案1】:

我找到了一个简单的解决方案,无需额外的数学运算……我创建了一个 0px 宽度的新元素来表示一个点。我将它放在我想要测量的角落,然后使用 getBoundingClientRect() 请求视口坐标,它返回一个矩形对象,其顶部、底部、左侧和右侧都相对于屏幕视口。由于点元素的宽度/高度为 0,因此顶部等于底部,左侧等于右侧。

clacDistancCornerCenter();


function clacDistancCornerCenter() {
  var center = document.getElementById('center').getBoundingClientRect();
  var corner = document.getElementById('corner').getBoundingClientRect();

  //alert("left =" + center.left + "top =" + center.top + "right =" + center.right + "bottom =" + center.bottom);

  var centerX = center.left;
  var centerY = center.top;


  var innersCornerX = corner.left;
  var innersCornerY = corner.top;

  //distance formula -> d = sqrt( pow( x2 - x1)  + pow( y2 - y1) )

  var distance = Math.sqrt(Math.pow(centerX - innersCornerX, 2) + Math.pow(centerY - innersCornerY, 2));

  document.getElementById('outRotated').innerHTML = "Distance center to corner: "+ distance;
}

function horizontal() {

  $('div').css('transform', 'rotate(0deg)');

}


function relocate(top, left) {
  var point = document.getElementById('corner');
  if (top) {
    point.style.bottom = 'auto';
    point.style.top = 0;
  } else {
    point.style.top = 'auto';
    point.style.bottom = 0;

  }

  if (left) {
    point.style.right = 'auto';
    point.style.left = 0;
  } else {
    point.style.left = 'auto';
    point.style.right = 0;
  }
  clacDistancCornerCenter();
}
div {
  top: 15%;
  left: 20%;
  width: 50%;
  height: 50%;
  border: 1px solid black;
  position: absolute;
  display: block;
  transform: rotate(25deg);
}
.point {
  width: 7px;
  height: 7px;
  background-color: blue;
  //border:3px solid blue;
  position: absolute;
  display: block;
}
#center {
  left: 50%;
  top: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="outRotated"></p>
<p id="outRotated"> Set points width and height to 0 to get the actual correct distance. For now the points are large for easy understanding</p>

<br/>
<button onclick="relocate(true,true)">Top Left</button>-------
<button onclick="relocate(true,false)">Top Right</button>
<br/>
<button onclick="relocate(false,true)">Bottom Left</button>
<button onclick="relocate(false,false)">Bottom Right</button>
<br/>
<button onclick="horizontal()">Horizontal</button>

<div id="outer">
  <span id="center" class="point" onclick="outputXY()"></span>
  <div id="mid">
    <div id="inner">
      <span id="corner" class="point" onclick="outputXY()"></span>
    </div>
  </div>
</div>

【讨论】:

  • 注意:这仅在转换元素的位置样式明确设置为相对或绝对时才有效。
【解决方案2】:

数学!

如果你有一个名为 Vector 的点类,它有一个 x 和一个 y 属性,你可以使用这样的方法来获取最终的 XY 坐标:

vA.getVectorRotated = function(vB, angle){
   angle = angle*Math.PI/180;
   return new Vector( (Math.cos(angle) * (this.x - vB.x)
                     - Math.sin(angle) * (this.y - vB.y) + vB.x),
                      (Math.sin(angle) * (this.x - vB.x) 
                     + Math.cos(angle) * (this.y - vB.y) + vB.y) );
};

【讨论】:

  • 这看起来很有趣,但需要对 vA 和 vB 进行更好的解释,以便那些不懂这个数学水平的人可以使用。
【解决方案3】:

要对任何 css 2d 变换执行此操作,您可以使用 getComputedStyle 并使用变换矩阵来获取变换后的坐标。

function calcElemTransformedPoint(elem, point)
{
    var style = getComputedStyle(elem);
    var transformOrigin = style.transformOrigin.split(' ').map(function(e)
    {
        // Remove 'px' and cast to number
        return +e.slice(0,-2);
    });
    var p = [point[0] - transformOrigin[0], point[1] - transformOrigin[1]];
    var transform = style.transform;
    // Matrix
    var m = [];
    if(transform.slice(0,7) === 'matrix(')
        m = transform.slice(7,-1).split(',').map(function(e){ return +e; });
    else
    {
        // 'matrix3d('
        var tmp = transform.slice(9,-1).split(',');
        m = [
            +tmp[0],
            +tmp[1],
            +tmp[4],
            +tmp[5],
            +tmp[12],
            +tmp[13]
        ];
    }
    // Matrix multiplication
    return [
        p[0] * m[0] + p[1] * m[2] + m[4] + transformOrigin[0],
        p[0] * m[1] + p[1] * m[3] + m[5] + transformOrigin[1]
    ];
}

Usage example

【讨论】:

    猜你喜欢
    • 2013-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-09
    • 2013-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多