如何解决CSS 旋转动画问题:创建从 270 度到 -90 度的平滑过渡
我正在尝试创建一个网络动画,其中一个矩形根据鼠标位置围绕浏览器窗口的中心点旋转(如下面的 gif 所示)。
动画 99% 正常工作,但我遇到了无法修复的边缘问题。请参阅 gif 以获取视觉参考:当鼠标位于屏幕右半部分时,动画按预期运行——当鼠标位于屏幕左半部分并与水平轴交叉时会出现问题,导致矩形翻转完整的 360 度,而不是平滑过渡。
这是因为矩形正在从 270 度快速捕捉到 90 度——两个角度在视觉上是相同的,但由于过渡动画,您可以观察到矩形翻转了整整 360 度。
如何解决此问题以确保屏幕左侧的平滑过渡?
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>
解决方法
跳转是由于 deg
从 360 变为 0。您可以在 mousemove 处理程序之外存储鼠标的运行旋转角度,并在处理程序中计算角度的变化,如下所示:
var rect = document.getElementById('orange_rect'),// Target rectangle
window_width = $(window).width(),// set window width
window_height = $(window).height(),// set window height
angle = 0,// The stored angle of the mouse [rad]
deg = 0,// The actual rotation angle [deg]
cX = 200,// The centre point of the rotation
cY = 200;
$(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) { //called whenever mouse moves in browser window
var x = e.pageX,// proportion representing mouse position from left of screen
y = e.pageY,// proportion representing mouse position from top of screen
ang = Math.atan2(y - cY,x - cX),// The current angle of the mouse related to the rotation centre
delta = ang - angle; // Change to the previous angle
angle += delta;
deg += delta * 180 / Math.PI;
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)';
});
#orange_rect {
position: fixed;
top: 100px;
left: 100px;
width: 200px;
height: 200px;
background: orange;
border-top: 5px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="orange_rect"></div>
值得注意的是,您不必将 deg
值限制在 0 - 360 的范围内,CSS 将根据任何给定值计算正确的角度。保持旋转角度中的“轮”,在旋转到下一轮时也能平滑旋转。
我能够使用变换矩阵解决这个问题,如下面的代码片段所示。据我所知,使用基于旋转的变换没有简单的解决方案。
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)';
rect.style.mozTransform = 'matrix(' + n1 + ',0)';
rect.style.msTransform = 'matrix(' + n1 + ',0)';
rect.style.oTransform = 'matrix(' + n1 + ',0)';
rect.style.transform = 'matrix(' + n1 + ',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>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。