微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

CSS 旋转动画问题:创建从 270 度到 -90 度的平滑过渡

如何解决CSS 旋转动画问题:创建从 270 度到 -90 度的平滑过渡

我正在尝试创建一个网络动画,其中一个矩形根据鼠标位置围绕浏览器窗口的中心点旋转(如下面的 gif 所示)。

动画 99% 正常工作,但我遇到了无法修复的边缘问题。请参阅 gif 以获取视觉参考:当鼠标位于屏幕右半部分时,动画按预期运行——当鼠标位于屏幕左半部分并与水平轴交叉时会出现问题,导致矩形翻转完整的 360 度,而不是平滑过渡。

这是因为矩形正在从 270 度快速捕捉到 90 度——两个角度在视觉上是相同的,但由于过渡动画,您可以观察到矩形翻转了整整 360 度。

如何解决此问题以确保屏幕左侧的平滑过渡?

enter image description here

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 举报,一经查实,本站将立刻删除。