如何将x、y坐标转换为角度?

53

Microsoft提供了一个出色的SVG渐变制作工具,因此IE9也可以使用“CSS3”渐变(单击自定义)。

我目前在我的FireworksDreamweaver扩展中利用它们的逻辑将渐变转换为SVG,但我只知道如何对标准的上、下、左、右方向进行转换。如果输入角度,我就不进行转换,因为我不知道如何将x1、x2、y1、y2转换为CSS3角度。

渐变生成器提供这样的值:x1 =“0%”y1 =“0%”x2 =“56.262833675564686%”y2 =“68.29999651227678%”

我不太擅长数学或三角学,所以能否有人帮帮我?如果可能的话,我还想在Sass mixin中使用相同的数学方法来做类似的事情。

6个回答

101
如果您从坐标中获取 deltaXdeltaY,那么使用 Math.atan2 可以返回其参数的商的反正切值。返回值单位为弧度。
var deltaX = x2 - x1;
var deltaY = y2 - y1;
var rad = Math.atan2(deltaY, deltaX); // In radians

那么你可以像这样简单地将它转换为度数:

var deg = rad * (180 / Math.PI)

enter image description here

编辑

我的初始答案中有一些错误。我相信在更新后的答案中已经解决了所有的问题。如果您认为这里存在问题,请在评论区留言。


2
deltaX将是x2-x1,而deltaY将是y2-y1。您的答案是正确的,但它是以弧度单位表示的,您忘记乘以(180 / Math.PI)以获得以度为单位的答案。 - Waleed Amjad
8
你应该使用 Math.atan2 - Phrogz
使用atan2函数时,应考虑到函数的不连续性,请参见下面的答案。 - pasx
4
我看到这个答案已经被编辑过了(它以前是使用Math.tan, 现在改成了Math.atan2),但仍然不完全正确。坐标应该是按(y,x)的顺序而不是(x,y)...我也觉得这很傻,但这就是 JavaScript。点击这里查看Math.atan2 的文档或者查看我的回答以获得更多细节信息。 - Matt
1
如果我知道角度但想找出 deltaX 和 deltaY 怎么办? - Imran Bughio
显示剩余3条评论

27

当前被接受的答案是错误的。首先,Math.tan 是完全错误的 - 我怀疑 Mohsen 的意思是 Math.atan,这只是一个笔误。

然而,正如其他对该答案的回应所述,你应该真正使用 Math.atan2(y, x)。常规反正切仅返回在 -pi/2 到 pi/2(第1象限和第4象限)之间的值,因为输入是有歧义的-反正切无法知道输入值属于第1象限还是第3象限,或者属于第2象限还是第4象限。

Math.atan2则可以使用给定的xy值来计算您所处的象限,并针对所有四个象限中的任何坐标返回适当的角度。然后,正如其他人所指出的那样,如果需要,您可以通过乘以(180/Math.pi)将弧度转换为度数。


4

不要使用Math.tan函数,而应该使用Math.atan2:

以下是一个使用示例:

deltaX = x2 - x1;
deltaY = y2 - y1;
deg = Math.atan2(deltaY, deltaX)*180.0/Math.PI;

这将返回一个度数,范围在<-180;180>之间。


我猜你的意思是:*(180 / Math.PI) - Timothée HENRY
3
他本来可以,但这无关紧要。 - bzeaman

-1

这个函数接受2个元素并返回它们中间的角度。

例如,我在世界地图上使用它,使飞机图像朝向城市方向旋转。

function degFromTwoElements(el1,el2){
    var x1,x2,y1,y2,cx1,xy1,cx2,cy2,deltaX,deltaY,dx,dy,rad,deg,shortest,number;
    x1 = el1.position().left;
    y1 = el1.position().top;
    x2 = el2.position().left;
    y2 = el2.position().top;
    cx1 = x1 - (el1.width() / 2);
    cy1 = y1 - (el1.height() / 2);
    cx2 = x2 - (el2.width() / 2);
    cy2 = y2 - (el2.height() / 2);

    deltaX = cx2 - cx1;
    deltaY = cy2 - cy1;
    y1 = Math.sqrt((Math.abs(deltaY)*Math.abs(deltaY))+(Math.abs(deltaX)*(Math.abs(deltaX))));
    x1 = 0;
    dy = deltaY-y1;
    dx = deltaX-x1;
    rad = Math.atan2(dy, dx);
    deg = rad * (360 / Math.PI);

    shortest;
    number = Math.abs(deg);
    if ((360 - number ) < number){
        shortest = 360 - number;
        console.log('shorter degree: ' + shortest);
        return shortest;
    } 
    else console.log('Angle is: ' + deg);
    return deg;

}

这与问题无关。 - Adam Pietrasiak
应该是 (180 / Math.PI); - sebhaase

-1

如果你在一个象限内

P1=(X0,Y0)

P2=(X1,Y1)

a=(X0-X1)

b=(Y0-Y2)

deltaX=((a)**2)**0.5
deltaY=((b)**2)**0.5
rad=math.atan2(deltaY, deltaX)
deg = rad * (360 / math.pi)
print deg

度数将在0~180之间


2
这句话是什么意思?它对现有答案有何补充? - Chris Maes
deltaX=((a)**2)**0.5 相当于 deltaX = a... "**2)**0.5" 互相抵消了... 这有什么意义呢? - macrocosme
@macrocosme 我认为他想要去除负值 ((-1)**2)**0.5 == 1。不过我认为这是错误的答案。 - Sos.

-2

var x,x1,x2,y,y1,y2;
var cells = 'cell0';
  var h,w;
  var cx,cy;
  var dx,dy;
  var derajat;
  var deg;
  var ang;
  var light;
  var control;
   function mouse_watch(event){
    x = event.clientX;
    y = event.clientY;
    cell_data(cells);
    koordinat(x2,y2);
    busur(derajat);
   }
   function koordinat(x2,y2){
    x2 = x-cx;
    y2 = y-cy;
    yk = y2;
    xk = x2;
   }
   function busur(derajat){

    y1 = Math.sqrt((Math.abs(yk)*Math.abs(yk))+(Math.abs(xk)*(Math.abs(xk))));
    x1 = 0;
    dy = yk-y1;
    dx = xk-x1;
    rad = Math.atan2(dy, dx);
    derajat = rad * (360 / Math.PI);
    cell = document.getElementById(cells);
    ang = cell.getElementsByClassName('angle0')[0];
    ang.style.transform = 'rotate('+derajat+'deg)';
    light = ang.getElementsByClassName('points')[0];
    light.style.height = y1+'px';
   }
   function cell_data(cells){
    cell = document.getElementById(cells);
    h = Number(cell.style.height.replace('px',''));
    w = Number(cell.style.width.replace('px',''));
    cy = Number(cell.style.top.replace('px',''))+h/2;
    cx = Number(cell.style.left.replace('px',''))+w/2;
   }
   .preview_engine{
    position: absolute;
    top: 0;
    left: 0;
    padding: 10px;
    background-color: #2E8AE6;
    color: white;
   }
   body{
    cursor: default;
    width: 100%;
    height: 100%;
    font-family: Arial;
    font-size: 12px;
   }
   .fieldwork{
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0px;
    left: 0px;
   }
   .cell{
    position: relative;
    transition : width 2s, height 2s, top 2s, left 2s;
    background-color: red;
   }
   .angle0{
    width: 200px;
    height: 200px;
    position: absolute;
    top: -75px;
    left: -75px;
    background-color: green;
    border-radius: 50%;
    opacity: 0.5;
    transition : width 2s, height 2s, top 2s, left 2s;
   }
   .points{
    width: 10px;
    height: 10px;
    position: absolute;
    left: 95px;
    top: 95px;
    background-color: red;
    border-radius: 1em;
    opacity: none;
   }
<div class="fieldwork" onmousemove="mouse_watch(event)">
<div class='cell' id="cell0" style="width:50px;height:50px;top:200px;left:400px;">
<div class="angle0">
<div class="points"></div>
</div>
</div>
</div>


虽然这是一个不错的小部件,但它并没有为任何答案增添什么...也没有回答问题... - Chris Maes
1
“so-ed-1”定理:随着一个stackoverflow问题的回答数量增加,每个答案中的代码量也会增加。“so-ed-2”定理:随着一个stackoverflow问题的回答数量增加,每个答案中的代码质量也会降低。 (抱歉我的讽刺) - Erhard Dinhobl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接