我知道Internet上有很多关于此主题的文章,但是我还没有解决问题。我认为三角函数的计算是正确的,但是也许我在JavaScript中弄乱了一些东西。
我的目标是计算圆(x,y)上的点,以便可以将sliderHead
移动到该位置。为此,我需要计算圆上按下/单击的点之间的角度-为此,我使用atan2
。接下来,我使用简单的三角函数来计算实际的X和Y:
let y = -Math.ceil(radius * Math.cos(deg));
let x = Math.ceil(radius * Math.sin(deg));
我知道我需要颠倒cosine
和sine
,因为我的起始位置实际上是90度而不是0,而我转动了CLOCKWISE而不是COUNTERCLOCKWISE,这在数学上是建议的。
起始值为0,因为sliderHead
的初始值位于圆的中心。起始值不是实际的0、0px,而是父级的中心。
您将在下图看到,我做的不正确,sliderHead位于条的后面。
这是我计算点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"
};
}
这里是我如何翻译sliderHead
:
moveSliderHeadPosition(point) {
this.sliderHead.style.transform = "translate(" + point["x"] + "," + point["y"] + ")";
}
如上所述,我尽力解决所有问题。我知道希望这里有人可以帮助我。
尝试将计算出的角度乘以或除以57.2957795
(度和弧度之间的转换)。
关于使用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>