圆上的计算点

问题描述 投票:1回答:2

我知道Internet上有很多关于此主题的文章,但是我还没有解决问题。我认为三角函数的计算是正确的,但是也许我在JavaScript中弄乱了一些东西。

我的目标是计算圆(x,y)上的点,以便可以将sliderHead移动到该位置。为此,我需要计算圆上按下/单击的点之间的角度-为此,我使用atan2。接下来,我使用简单的三角函数来计算实际的X和Y:

let y = -Math.ceil(radius * Math.cos(deg));
let x = Math.ceil(radius * Math.sin(deg));   

我知道我需要颠倒cosinesine,因为我的起始位置实际上是90度而不是0,而我转动了CLOCKWISE而不是COUNTERCLOCKWISE,这在数学上是建议的。

起始值为0,因为sliderHead的初始值位于圆的中心。起始值不是实际的0、0px,而是父级的中心。

您将在下图看到,我做的不正确,sliderHead位于条的后面。

enter image description here

这是我计算点x,y的代码:

 testCalc(event) {
        let deg = Math.atan2(event.pageY - this.centerY, event.pageX - this.centerX);

        console.log(deg);

        let radius = this.options.radius;

        let y = -Math.ceil(radius * Math.cos(deg));
        let x = Math.ceil(radius * Math.sin(deg));      

        return {
            "x": x + "px",
            "y": y + "px"
        };

    }

这是我的HTML内sliderHead元素的位置:enter image description here

这里是我如何翻译sliderHead

    moveSliderHeadPosition(point) {
           this.sliderHead.style.transform = "translate(" + point["x"] + "," + point["y"] + ")";
   } 

如上所述,我尽力解决所有问题。我知道希望这里有人可以帮助我。

javascript geometry trigonometry
2个回答
0
投票

尝试将计算出的角度乘以或除以57.2957795(度和弧度之间的转换)。


0
投票

关于使用atan2很不错!查看您的代码对我来说似乎很正确,尽管也许只需要减去sliderHead的一半大小就这么简单?

这是我汇总起来进行测试的示例:

function showCoords(event) {
  var x = event.clientX;
  var y = event.clientY;
  var xn = x / window.innerWidth;
  var yn = y / window.innerHeight;
  var result = Math.atan2(x, y);
  var coor = `X: ${x}, Y: ${y} > X1: ${xn.toFixed(2)}, Y1: ${yn.toFixed(
    2
  )} ~ ${result.toFixed(
    2)}`;
  document.getElementById("demo").innerHTML = coor;
}

function moveGrabber(event) {
  // get our grabber and track as well as their bounding rectangles
  var grabber = document.querySelector(".grabber");
  var grabberRect = grabber.getBoundingClientRect();
  var track = document.querySelector(".track");
  var trackRect = track.getBoundingClientRect();
  var trackRadius = trackRect.width / 2;

  // get our window center
  var windowCenterX = window.innerWidth / 2;
  var windowCenterY = window.innerHeight / 2;

  // get the angle around the window center
  var x = event.clientX;
  var y = event.clientY;
  var angle = Math.atan2(x - windowCenterX, y - windowCenterY);

  // get the point on the circle
  var circleX = Math.sin(angle) * trackRadius + windowCenterX;
  var circleY = Math.cos(angle) * trackRadius + windowCenterY;

  // subtract half the size of the grabber so that it is centered on the track
  var posX = circleX - grabberRect.width / 2;
  var posY = circleY - grabberRect.height / 2;

  grabber.style.left = `${posX}px`;
  grabber.style.top = `${posY}px`;
}

function moveGrabberWithX(event) {
  // get our grabber and track as well as their bounding rectangles
  var grabber = document.querySelector(".grabber");
  var grabberRect = grabber.getBoundingClientRect();
  var track = document.querySelector(".track");
  var trackRect = track.getBoundingClientRect();
  var trackRadius = trackRect.width / 2;

  // get the mouse position and the normalized version in the range of [0,1]
  var x = event.clientX;
  var xn = x / window.innerWidth;

  // get the center of the window
  var windowCenterX = window.innerWidth / 2;
  var windowCenterY = window.innerHeight / 2;

  // get the point on the circle
  // this uses the normalized x position of the mouse [0,1]
  // and multiplies it by 2PI which gives you a circle
  var circleX = Math.sin(xn * Math.PI * 2) * trackRadius + windowCenterX;
  var circleY = Math.cos(xn * Math.PI * 2) * trackRadius + windowCenterY;

  // subtract half the size of the grabber so that it is centered on the track
  var posX = circleX - grabberRect.width / 2;
  var posY = circleY - grabberRect.height / 2;

  grabber.style.left = `${posX}px`;
  grabber.style.top = `${posY}px`;
}
html,
body {
  margin: 0px;
  padding: 0px;
}
.center {
  position: absolute;
  top: 0px;
  left: 0px;
  width: 100vw;
  height: 100vh;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: gray;
}

.track {
  width: 300px;
  height: 300px;
  background: rgb(13, 88, 134);
  border-radius: 50%;
}

.grabber {
  position: absolute;
  top: 0px;
  left: 0px;
  width: 25px;
  height: 25px;
  background: coral;
  border-radius: 50%;
}

.label {
  position: absolute;
  top: 0px;
  left: 0px;
  width: 100%;
  /* display: flex; */
}
p {
  background: darkgray;
  font-family: "Courier New", Courier, monospace;
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Static Template</title>
    <link rel="stylesheet" href="styles.css" />
    <script src="script.js"></script>
  </head>
  <body>
    <div class="center" onmousemove="moveGrabber(event); showCoords(event);">
      <div class="track" />
      <div class="grabber" />
    </div>
    <div class="label">
      <p id="demo" />
    </div>
  </body>
</html>
© www.soinside.com 2019 - 2024. All rights reserved.