简体   繁体   English

在Javascript中找到圆与线的相交点

[英]Find the Points of Intersection of a Circle with a Line in Javascript

I'm trying to animate a given element to go around a pre-defined radius and I'm having trouble getting the position of the element at a Y point given. 我正在尝试给定元素设置动画以使其绕预定半径移动,而我无法在给定的Y点获得该元素的位置。

I'm trying to find each point with the circle equation, but I can only get one point out of the two possible ones. 我试图用圆方程找到每个点,但是我只能从两个可能的点中得到一个点。

圆方程 In Javascript, I use Math.sqrt( Math.pow(radius, 2) - Math.pow(y, 2) , 2) to get the point. 在Javascript中,我使用Math.sqrt( Math.pow(radius, 2) - Math.pow(y, 2) , 2)来说明问题。 assuming the center of the of the circle is 0,0. 假设圆的中心为0,0。 but then I need to translate it to pixels on the screen since there are no negative pixels in positions on the browser. 但随后我需要将其转换为屏幕上的像素,因为浏览器上的位置没有负像素。

All the sizing is relative to the window. 所有大小均与窗口有关。 so the radius, for example, is 80% of the height of the window in my tests. 因此半径在我的测试中是窗口高度的80%。

Also, I'm trying to calculate what the distance of the element between each frame should be for the duration, but I'm not using it yet because I try to fix the issue above first. 另外,我正在尝试计算元素在持续时间内每帧之间的距离,但是我尚未使用它,因为我先尝试解决上述问题。

This is what I have(a cleaned up version): 这是我所拥有的(清理版本):

let height = window.innerHeight * 0.8,
    radius = height / 2,
    circumferance = (radius * 2) * Math.PI,
    container = document.getElementById('container'),
    rotating = document.querySelector('.rotating'),
    centerX = radius - (rotating.offsetWidth / 2),
    centerY = radius - (rotating.offsetHeight / 2),
    duration = 10,
        stepDistance = circumferance / 16;

// Setting the dimensions of the container element.
container.style.height = height + 'px';
container.style.width = height + 'px';

// return positive X of any given Y.
function getXOffset(y) {
    return Math.sqrt( Math.pow(radius, 2) - Math.pow(y, 2) , 2);
}

// Setting the position of the rotating element to the start.
rotating.style.top = 0 + 'px';
rotating.style.left = centerX + 'px';

setInterval(() => {
  let top = parseInt(rotating.style.top),
        y = radius - top;

    rotating.style.top = (top + 1) + 'px';
    rotating.style.left = (centerX + getXOffset(y)) + 'px';
}, 16);

Here is a fiddle with a bit more code for trying to get the right amount of distance between points for a smoother animation(currently needs fixing, but it doesn't bother me yet.) https://jsfiddle.net/shock/1qcfvr4y/ 这是一个带有更多代码的小提琴,用于尝试使点之间的距离保持适当的距离,以使动画更流畅(当前需要修复,但这还不打扰我。) https://jsfiddle.net/shock/1qcfvr4y /

Last note: I know that there might be other ways to do this with CSS, but I chose to use javascript for learning purposes. 最后一点:我知道CSS可能还有其他方法,但是我选择使用javascript进行学习。

Math.sqrt would only return the positive root. Math.sqrt将仅返回正根。 You'll have to account for the negative value based on the application. 您必须根据应用程序考虑负值。 In this case, you need the positive x value during the 1st half of the cycle and negative during the 2nd half. 在这种情况下,您需要在循环的前半部分输入正x值,在后半部分输入负值x To do that, you should implement a method to track the progress and reverse the sign accordingly. 为此,您应该实现一种方法来跟踪进度并相应地反转符号。

Here is a sample . 这是一个样本 I modified upon yours. 我修改了你的。

edit: 编辑:

Instead of Math.sqrt( Math.pow(radius, 2) - Math.pow(y, 2) , 2) You can use the full formula to get x if you do not want to assume origin as center, which in this case is Math.sqrt( Math.pow(radius, 2) - Math.pow((actualY - centerY), 2) , 2) 代替Math.sqrt( Math.pow(radius, 2) - Math.pow(y, 2) , 2)如果您不想将原点作为中心,则可以使用完整公式来获取xMath.sqrt( Math.pow(radius, 2) - Math.pow((actualY - centerY), 2) , 2)

explanation: 说明:

The original equation (xa)² + (y'-b)² = r² becomes x = √(r² - (y'-b)²) + a 原始方程(xa)² + (y'-b)² = r²变为x = √(r² - (y'-b)²) + a

Assuming .rotating box have 0 width and height. 假设.rotating盒的宽度和高度为0。

The variable equivalents in your code are centerX = a , centerY = b . 代码中的等效变量为centerX = acenterY = b By assuming origin as center you're basically doing a pre-calculation so that your y value becomes the equivalent of (y'-b) . 通过以原点为中心,基本上就是在进行预先计算,以便y值等于(y'-b) Hence x = √(r² - y²) + a is valid. 因此, x = √(r² - y²) + a是有效的。

At initial state top = 0 在初始状态时, top = 0

ie (y'-b) => height - centerY . (y'-b) => height - centerY In your code y = radius => height/2 . 在您的代码中y = radius => height/2 Now (height - centerY) being equal to (height/2) is a side effect of your circle being bound by a square container whose height determines the y value. 现在(height - centerY)等于(height/2)是圆被正方形容器限制的副作用,该正方形容器的高度决定y值。

In other words, when you use origin as center, you are taking the center offsets outside of circle equation and handling it separately. 换句话说,当您使用原点作为中心时,您要在圆方程之外获取中心偏移并分别进行处理。 You could do the same thing by using the whole formula, that is, x = √(r² - (y'-b)²) + a 您可以通过使用整个公式来完成相同的操作,即x = √(r² - (y'-b)²) + a

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM