【问题标题】:Javascript point to point angle calculationJavascript点对点角度计算
【发布时间】:2013-04-04 02:22:28
【问题描述】:

我们得到 3 分:startendma​​il

邮件图像,从起点和终点沿曲线移动,这是由 jQuery animate 完成的。

现在下一步是让邮件图像在动画运行时旋转。所以在起点和终点,它会旋转 0 度,但在制作动画时,它应该面向动画的路径旋转。 (见图)

我尝试过的:

JSFiddle

// Init dom elements
var $start = $('#start');
var $end = $('#end');
var $mail = $('#mail');

// Get position coordinates
var startPos = $start.position();
var endPos = $end.Position();

// Angle calculation
var getAngle = function(currX, currY, endX, endY) {
  var angle = Math.atan2(currX - endX, currY - endY) * (180 / Math.PI);

  if (angle < 0) {
    angle = Math.abs(angle);
  } else {
    angle = 360 - angle;
  }

  return angle;
};

// Mail angle
var getMailAngle = function() {
  var currPos = $mail.position();
  var endPos = $end.position();
  return getAngle(currPos.left, currPos.top, endPos.left, endPos.top);
};

// Animate
$mail.animate({top: endPos.top, left: endPos.left}, {
  specialEasing: {left: "easeInSine", top: "linear"},

  // Executed each "animation" frame, so we rotate here.
  step: function() {
    var angle = getMailAngle();
    $(this).css('transform', 'rotate(' + angle + 'deg'));
  }
});

但上面的代码不正确,开始/结束时角度不朝上,我对几何数学的经验很少,所以非常感谢旋转计算的帮助。

【问题讨论】:

  • 我不明白为什么它应该在开始/结束时面朝上,因为图中的路径没有退出起点并以 90° 角进入终点。
  • @MattBall 真正的动画确实以 90° 角开始和结束,图像在 Photoshop 中很快就出现了,遗憾的是有偏移
  • 这是你看到的吗? jsfiddle.net/R5dRd
  • 一个 JSFiddle 将有助于了解发生了什么问题。 y 坐标之间的差异应该是Math.atan2 的第一个参数。此外,看起来您正在根据连接当前位置和结束位置(割线)的线的斜率计算角度。确实,您想要的是近似动画曲线的局部斜率(切线)。一个合理的方法是在当前位置和上一步的位置之间做atan2
  • 看看发生了什么,似乎获取当前位置并不能产生稳定的结果,因为旋转会影响位置坐标。你必须找到一种方法来弥补这一点。希望我能提供更多帮助,但我得回去解决我自己的问题 :)

标签: javascript animation rotation geometry angle


【解决方案1】:

首先,您需要使用以相同“角度”开始和结束的缓动动画。如果您查看不同的 easing optionsswingeaseInOutQuadeaseInOutSine 是一些有效选项。

要计算角度的近似值,您可以查看邮件图标的当前位置及其下一个位置(在下一个动画帧中)。要获得良好的近似值,您需要使用缓动函数“手动”计算当前位置和下一个位置。这也意味着您需要手动控制动画。

这是一个代码sn-p,你也可以在JSFiddle上看到它。

// Init dom elements
var $start = $('#start');
var $end = $('#end');
var $mail = $('#mail');

// Get position coordinates
var startPos = $start.offset();
var endPos = $end.offset();

// Angle calculation
var getAngle = function(currX, currY, endX, endY) {
  var angle = Math.atan2(currX - endX, currY - endY) * (180 / Math.PI);

  if (angle < 0) {
    angle = Math.abs(angle);
  } else {
    angle = 360 - angle;
  }

  return angle;
};

// Animate
var maxframe = 1000;
$({frame: 0}).animate({frame: maxframe}, {
    easing: "linear",
    duration: 1000,

  // Executed each "animation" frame, so we rotate here.
  step: function() {
      var easing = $.easing.easeInOutQuad;
      var left = easing(0, this.frame, startPos.left, endPos.left - startPos.left, maxframe);
      var leftNext = easing(0, this.frame+1, startPos.left, endPos.left - startPos.left, maxframe);

      var top = startPos.top + (endPos.top - startPos.top) * this.frame / maxframe;
      var topNext = startPos.top + (endPos.top - startPos.top) * (this.frame + 1) / maxframe;

      var angle = getAngle(left, top, leftNext, topNext);     
      $mail.offset({left: left, top: top});
      $mail.css('transform', 'rotate(' + angle + 'deg)');
  },

  // Set the final position
  complete: function() {
      $mail.offset($end.offset());
      $mail.css('transform', ''); 
  }  
});

【讨论】:

  • 这些公式将导致邮件图标始终尝试直接指向最终点,而不一定与其当前路径相切。
  • 嗨赛斯。不,它并不总是指向最后一点。您可以通过制作更复杂的缓动函数来看到这一点。看到这个JSFiddle
  • 你是对的。我认为您的代码 sn-p 与前面提到的相同(它总是指向最后一点)。这在 JSFiddle 上完美运行。
猜你喜欢
  • 1970-01-01
  • 2021-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-04
  • 1970-01-01
相关资源
最近更新 更多