12
[CATransaction begin];
            [CATransaction setAnimationDuration:5];
            CGAffineTransform currentTransform = squareLayer.affineTransform;
            CGFloat angle = M_PI;

            squareLayer.affineTransform = CGAffineTransformRotate(currentTransform, angle);
            [CATransaction commit];

[CATransaction begin];
            [CATransaction setAnimationDuration:5];
            CGAffineTransform currentTransform = squareLayer.affineTransform;
            CGFloat angle = (M_PI * -1);

            squareLayer.affineTransform = CGAffineTransformRotate(currentTransform, angle);
            [CATransaction commit];

我原以为-1会改变方向,但显然不是?

4

8 回答 8

15

角度是一样的。要走一圈,你需要 2 * Pi,所以半圈是 Pi。如果您使用 -Pi,它将在同一点结束。

编辑:如果你需要让它顺时针转动,你可以稍微偏离-Pi。例如,使用 -3.141593 代替 -M_PI。

于 2012-05-04T09:11:26.543 回答
9

刚刚遇到这个问题,虽然@radicalraid 的解决方案运行良好,但我更喜欢在旋转之前调整起始角度,而不是旋转到小于所需终点的角度。此外,您可以CALayer使用动画块为变换设置动画。

我的代码:

// iOS will rotate the shortest distance to the end angle,
// using counter-clockwise if equal.
// Force the rotation to open clockwise and close counter-clockwise by bumping
// the initial angle
CGFloat startRadians, endRadians;
if (isOpening) {
    startRadians = 0.01f;
    endRadians = M_PI;

}
else {
    startRadians = M_PI - 0.01f;
    endRadians = 0.0f;
}

self.myImageView.layer.affineTransform = CGAffineTransformMakeRotation(startRadians);

[UIView animateWithDuration:0.3f
                 animations:^{
                     self.myImageView.layer.affineTransform = CGAffineTransformMakeRotation(endRadians);
                 }];
于 2013-06-24T21:14:40.187 回答
5

我对 Core animatinon 的体验与 Apple 的引用不符。我发现唯一重要的是最终角度值。正 pi 和负 pi 旋转产生相同的变换矩阵,因此系统无论如何都会逆时针旋转。

我所做的以特定方向旋转或完整 360 度旋转是使用像 transform.rotation.z 这样的类型创建显式 CABasicAnimation,填充模式设置为 kCAFillModeForwards,并且只提供一个 toValue . 这会导致动画从前一个值开始。然后,您可以设置一个轮换,该轮换占您所需的总轮换的偶数部分,并给它一个重复计数。

例如,下面的代码创建了一个旋转 5 个四分之一圈或 450 度的动画。如果你想顺时针旋转 180 度,你可以旋转 pi/2,重复计数为 2。对于逆时针,使用 -pi/2,重复计数为 2。

  CABasicAnimation* rotate =  [CABasicAnimation animationWithKeyPath: 
    @"transform.rotation.z"];
  rotate.removedOnCompletion = FALSE;
  rotate.fillMode = kCAFillModeForwards;

  //Do a series of 5 quarter turns for a total of a 1.25 turns
  //(2PI is a full turn, so pi/2 is a quarter turn)
  [rotate setToValue: [NSNumber numberWithFloat: -M_PI / 2]];
  rotate.repeatCount = 5;

  rotate.duration = duration/rotate.repeatCount * 2 ;
  rotate.beginTime = start;
  rotate.cumulative = TRUE;
  rotate.timingFunction = [CAMediaTimingFunction 
    functionWithName:kCAMediaTimingFunctionLinear];
于 2012-05-05T20:52:50.517 回答
4

编辑:而不是 -M_PI 使用 -3 * M_PI,逆时针

并删除相反方向的“-”符号。

于 2016-07-06T06:16:41.953 回答
2

看看这个先前的问题:Force 顺时针/逆时针旋转 UIImageView的 CABasicAnimation 代码有点不同,但它确实有效。

于 2012-05-04T09:17:00.637 回答
2

这是来自苹果文档的引用“在 iOS 中,正值指定逆时针旋转,负值指定顺时针旋转。” 您是否尝试过这样做:

squareLayer.affineTransform = CGAffineTransformRotate(currentTransform, -M_PI);

这就是我过去所做的所有顺时针旋转。

于 2012-05-04T09:20:56.567 回答
1

这是我用来使其始终顺时针if endAngle > startAngle和逆时针旋转的功能if startAngle > endAngle。(例如动画不应该“越过 2*pi 线”)

private func rotate(view: UIView, from startAngle: CGFloat, to endAngle: CGFloat) {
    let midAngle = (startAngle.truncatingRemainder(dividingBy: 2 * .pi) + endAngle.truncatingRemainder(dividingBy: 2 * .pi)) / 2

     UIView.animateKeyframes(withDuration: UIView.inheritedAnimationDuration, delay: 0, options: .calculationModeCubicPaced, animations: {
        UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0) {
            view.transform = CGAffineTransform(rotationAngle: midAngle)
        }
        UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0) {
            view.transform = CGAffineTransform(rotationAngle: endAngle)
        }
    }, completion: nil)
}

您可以从另一个 UIView.animate 块内部调用它,以使用其他东西对其进行动画处理。例如:

UIView.animate(withDuration: 1) {
   rotate(view: view, from: .pi * 0.25, to: 1.5 * .pi)
   otherView.alpha = 1
}

使用该.calculationModeCubicPaced选项很重要,否则您必须手动指定相对开始时间和持续时间

于 2019-03-15T21:10:42.953 回答
0

同意 Duncan 和 XJones 的观点。最终价值似乎是最重要的。然后 CA 将找到最短路径。

使用 XJones 的想法。这似乎对我有用:

private let angleRadians = CGFloat(M_PI)
private let angleRadiansOffset = CGFloat(0.1 * M_PI/180.0)

let turnAngle = angleRadians - angleRadiansOffset;

//pre-rotate by an 'invisible amount', to force rotation in the same direction every time
primView.layer.transform = CATransform3DRotate(primView.layer.transform, angleRadiansOffset, 0.0, 1.0, 0.0)

UIView.animateKeyframesWithDuration(duration, delay: 0, options: [.BeginFromCurrentState], animations: { () -> Void in

    UIView.addKeyframeWithRelativeStartTime(0, relativeDuration: 0.8, animations: { () -> Void in

        //now we will complete the rotation to the correct end value
        primView.layer.transform = CATransform3DRotate(primView.layer.transform, turnAngle, 0.0, 1.0, 0.0)

    })

    //... other code ....

}) { (finished) -> Void in

}
于 2016-02-26T15:04:50.673 回答