I had a menu design idea that involves a central cursor that points to indicate what menu item is currently being selected. I achieved this using some JavaScript code that takes a list of fixed angles that represent the buttons and then calculates whether to rotate clockwise or anti-clockwise based on whichever would require less degrees to reach. The issue I encountered however was that upon going from these 2 angles (222° to 115° and vice versa) the arrow would not take the fastest route and spin the opposite direction.
After doing some research what I believe to actually be happening is the cursor is resetting to 0° so that it completes the circle before then making its way to the selected angle from the zero point thus causing it to go the wrong direction. I read a few answers on here and did some general research on the rotate function as a whole but have been unable to find a case that is similar enough to mine nor intuit a way in-which I could fix it myself (web development as a whole is new to me). I would ideally like for it to ignore the rule that compels it to complete the circle and instead just point to the supplied angle though I am aware that is likely impossible to do with css’s rotate tool, so if there is anything that would do the same to that effect it would be much appreciated. I made a functional example to showcase my issue in a jsfiddle. https://jsfiddle.net/u3w4vz1n/latest/
const angles = { // Dictionary of where we want our static angle positions to be
button1: 290,
button2: 222,
button3: 115,
button4: 75,
button5: 0
}
var cursor = document.getElementById("cursor")
var currentAngle = 0;
$(".button").hover(function() { // When mouse enters button area
let next_angle = angles[this.id];
let turn_radius = 0;
let clockwise = (Math.abs(next_angle - currentAngle) < 180) ? true : false; // Calculates which direction is less degrees from source and returns boolean
if (clockwise) {
turn_radius = (next_angle - currentAngle);
} else {
turn_radius = "-" + (360 - Math.abs(next_angle - currentAngle));
}
cursor.style.rotate = turn_radius + "deg";
});
.button {
display: block;
z-index: -1;
position: absolute;
border: 4px solid;
border-radius: 45%;
text-decoration: none;
text-align: center;
font: bold;
font-size: medium;
background-color: white;
}
#button1 {
width: 30%;
height: 15%;
top: 40%;
left: 15%;
transform: translate(-40%, -15%);
}
#button2 {
width: 30%;
height: 15%;
top: 75%;
left: 25%;
transform: translate(-75%, -25%);
}
#button3 {
width: 30%;
height: 15%;
top: 80%;
left: 85%;
transform: translate(-80%, -85%);
}
#button4 {
width: 30%;
height: 15%;
top: 40%;
left: 75%;
transform: translate(-40%, -75%);
}
#button5 {
width: 30%;
height: 15%;
top: 10%;
left: 35%;
transform: translate(-10%, -35%);
}
#cursor {
width: 100px;
height: 100px;
position: absolute;
top: 40%;
left: 40%;
transition: all 0.25s ease-out;
-moz-transition: all 0.25s ease-out;
-ms-transition: all 0.25s ease-out;
-o-transition: all 0.25s ease-out;
-webkit-transition: all 0.25s ease-out;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<title>Main Menu</title>
<link rel="stylesheet" href="index.css">
</head>
<body style="background-color: white;">
<img src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Ftse1.mm.bing.net%2Fth%3Fid%3DOIP.sVcpgS1I_6kEJvuOecuuUgHaHa%26pid%3DApi&f=1&ipt=00bebfbdf248c4677c3ad5a9f6910bdfbd564aa401d634006f527981942f13d6&ipo=images" id="cursor">
<a href="#" id="button1" class="button">Button1</a>
<a href="#" id="button2" class="button">Button2</a>
<a href="#" id="button3" class="button">Button3</a>
<a href="#" id="button4" class="button">Button4</a>
<a href="#" id="button5" class="button">Button5</a>
<script src="menu_select.js"></script>
</body>
</html>
2
Answers
This problem is caused because every time you update the angle it starts with 0 degrees instead of the shortest path. Update your JS function as below:
The rotation is clockwise. This means if we either going to a higher degree (clockwise) or lower degree (counterclockwise). So if we’re at degree
x
and need to go toy
we either go toy + 360
,y - 360
ory
so that the difference is smaller than 180° (half circle). For example, from 350° to 10° we actually need to go to 370° so that diff would be only 20° rather than -340° had we gone straight to 10°.See also Rotating a line to look at the mouse with linear interpolation causes jumping