How to convert x,y coordinates to an angle?

2019-01-22 11:44发布

Microsoft provide an excellent SVG gradient maker so IE9 can also have "CSS3" gradients (click Custom).

I currently utilise their logic for my Fireworks and Dreamweaver extensions to convert gradients to SVG, but I only know how to do it for standard top, bottom, left, right directions. If you enter an angle, I don't do the conversion, because I'm not sure how I would convert x1, x2, y1, y2 to CSS3 angle degrees.

The gradient generator provides values like this: x1="0%" y1="0%" x2="56.262833675564686%" y2="68.29999651227678%"

I'm not great with mathematics or trigonometry, so could somebody help me out? I'd also like to use the same math in a Sass mixin to do a similar thing, if possible.

6条回答
Explosion°爆炸
2楼-- · 2019-01-22 12:00

Instead of using Math.tan function You should use Math.atan2:

Here is an example of use:

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

and this will return a degree from <-180;180>.

查看更多
趁早两清
3楼-- · 2019-01-22 12:03

If you in a Quadrant

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

the deg will between 0 ~ 180

查看更多
Root(大扎)
4楼-- · 2019-01-22 12:04

If you get deltaX and deltaY from your coordinates then Math.atan2 returns the arctangent of the quotient of its arguments. The return value is in radians.

var deltaX = x2 - x1;
var deltaY = y2 - y1;
var rad = Math.atan2(deltaY, deltaX); // In radians

Then you can convert it to degrees as easy as:

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

enter image description here

Edit

There was some bugs in my initial answer. I believe in the updated answer all bugs are addressed. Please comment here if you think there is a problem here.

查看更多
SAY GOODBYE
5楼-- · 2019-01-22 12:12

This function takes 2 elements and returns the degree between the middle of the elements.

For example, I used it on a world map, to make the image of plane rotate in the direction of a city.

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;

}
查看更多
混吃等死
6楼-- · 2019-01-22 12:21

The currently accepted answer is incorrect. First of all, Math.tan is totally wrong -- I suspect Mohsen meant Math.atan and this is just a typo.

However, as other responses to that answer state, you should really use Math.atan2(y,x) instead. The regular inverse tangent will only return values between -pi/2 and pi/2 (quadrants 1 and 4) because the input is ambiguous -- the inverse tangent has no way of knowing if the input value belongs in quadrant 1 vs 3, or 2 vs 4.

Math.atan2, on the other hand, can use the xy values given to figure out what quadrant you're in and return the appropriate angle for any coordinates in all 4 quadrants. Then, as others have noted, you can just multiply by (180/Math.pi) to convert radians to degrees, if you need to.

查看更多
混吃等死
7楼-- · 2019-01-22 12:25

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>

查看更多
登录 后发表回答