I am trying to create a web animation where a rectangle rotates around the centre point of the browser window depending on the mouse position (as shown in the gif below).
The animation is 99% working, but I've run into an edge case issue that I am unable to fix. See gif for a visual reference: the animation behaves as desired when the mouse is in the right half of the screen--the issue occurs when the mouse is in the left half of the screen and crosses the horizontal axis, causing the rectangle to flip a full 360 degrees instead of transitioning smoothly.
This is because the rectangle is quickly snapping from 270 degrees to 90 degrees--both angles are visually the same, but due to transition animations you can observe the rectangle flipping a full 360 degrees.
How can I fix this issue to ensure a smooth transition on the left-side of the screen?
var rect = document.getElementById('orange_rect'); // Target rectangle
var window_width = $(window).width();
var window_height = $(window).height();
$(window).resize(function() { //set window width and height again everytime the window is resized
var window_width = $(window).width();
var window_height = $(window).height();
});
// Update rotation degrees on mousemove
$(document).mousemove(function(e) {
var x_pos = e.pageX / window_width;
var y_pos = e.pageY / window_height;
if (y_pos >= 0.5) {
var deg = 270 - (x_pos * 180);
} else if (y_pos < 0.5) {
var deg = (x_pos * 180) - 90;
};
rect.style.webkitTransform = 'rotate(' + deg + 'deg)';
rect.style.mozTransform = 'rotate(' + deg + 'deg)';
rect.style.msTransform = 'rotate(' + deg + 'deg)';
rect.style.oTransform = 'rotate(' + deg + 'deg)';
rect.style.transform = 'rotate(' + deg + 'deg)';
});
body {
overflow: hidden;
}
#orange_rect {
/* Homepage orange rect */
background-color: #FF4734;
height: 100vh;
width: 200vw;
overflow: hidden;
position: absolute;
top: 50vh;
margin-right: auto;
margin-left: -50vw;
transform-origin: 50% 0;
transition: transform 0.3s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<div id="orange_rect"></div>
</body>
I was able to solve the issue using transform matrices as demonstrated in the snippet below. There is no easy solution using rotation-based transform, as far as I can tell.
var rect = document.getElementById('orange_rect'); // Target rectangle
var window_width = $(window).width();
var window_height = $(window).height();
$(window).resize(function() { //set window width and height again everytime the window is resized
var window_width = $(window).width();
var window_height = $(window).height();
});
// Update rotation degrees on mousemove
$(document).mousemove(function(e) {
var window_width = $(window).width();
var window_height = $(window).height();
var x_pos = e.pageX / window_width; // proportion mouse position from left
var y_pos = e.pageY / window_height; // proportion mouse poisiton from top
if (x_pos <= 0.5) { // If mouse is on the left half of the screen
if (y_pos <= 0.5) { // If mouse is in top-left quadrant
n1 = 2 * x_pos;
n2 = -1 + 2 * x_pos;
n3 = 1 - 2 * x_pos;
n4 = n1;
}
if (y_pos > 0.5) { // If mouse is in bottom-left quadrant
n1 = -2 * x_pos;
n2 = -1 + 2 * x_pos;
n3 = 1 - 2 * x_pos;
n4 = n1;
}
} else if (x_pos > 0.5 && x_pos <= 1) { // If mouse is on the right half of the screen
if (y_pos <= 0.5) { // If mouse is in top-right quadrant
n1 = 1 - 2 * (x_pos - 0.5);
n2 = 2 * (x_pos - 0.5);
n3 = -2 * (x_pos - 0.5)
n4 = n1
}
if (y_pos > 0.5) { // If mouse is in bottom-right quadrant
n1 = -1 + 2 * (x_pos - 0.5);
n2 = 2 * (x_pos - 0.5);
n3 = -2 * (x_pos - 0.5)
n4 = n1
}
};
// console.log(n1)
rect.style.webkitTransform = 'matrix(' + n1 + ',' + n2 + ',' + n3 + ',' + n4 + ',0,0)';
rect.style.mozTransform = 'matrix(' + n1 + ',' + n2 + ',' + n3 + ',' + n4 + ',0,0)';
rect.style.msTransform = 'matrix(' + n1 + ',' + n2 + ',' + n3 + ',' + n4 + ',0,0)';
rect.style.oTransform = 'matrix(' + n1 + ',' + n2 + ',' + n3 + ',' + n4 + ',0,0)';
rect.style.transform = 'matrix(' + n1 + ',' + n2 + ',' + n3 + ',' + n4 + ',0,0)';
});
body {
overflow: hidden;
}
#orange_rect {
/* Homepage orange rect */
background-color: #FF4734;
height: 200vh;
width: 200vw;
overflow: hidden;
position: absolute;
top: 50vh;
margin-right: auto;
margin-left: -50vw;
transform-origin: 50% 0;
transition: transform 0.3s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<div id="orange_rect"></div>
</body>