如何在NSImageView中实现NSImage的连续旋转?

时间:2012-05-31 01:15:28

标签: objective-c macos cocoa core-animation quartz-2d

未来观众:

我已经设法完成了这个旋转动画,并且可以在问题上找到带描述的代码。 NSImage rotation in NSView is not working

在继续之前,请立即投票Duncan C。因为我设法从他的回答中实现这一轮换。


我有这样的图像,

enter image description here

我想继续旋转此同步图标,在另一个线程上。现在我尝试使用Quartz编辑器并将动画添加到QCView中,但它具有非常疯狂的效果并且非常慢。

问题:

如何以极低的处理费用连续旋转此图像?

努力

我阅读了CoreAnimation,Quartz2D文档,但我找不到让它工作的方法。到目前为止我唯一知道的是,我必须使用

  • 的CALayer
  • CAImageRef
  • 的AffineTransform
  • NSAnimationContext

现在,我不期待代码,但对伪代码的理解会很棒!

2 个答案:

答案 0 :(得分:15)

让物体旋转超过180度实际上有点棘手。问题是你为结束旋转指定了一个变换矩阵,系统决定向另一个方向旋转。

我所做的是创建一个小于180度的CABasicAnimation,设置为加法,并重复计数。动画中的每个步骤都会为对象设置更多动画。

以下代码来自iOS应用程序,但该技术在Mac OS中是相同的。

  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 = 11;

  rotate.duration = duration/2;
  rotate.beginTime = start;
  rotate.cumulative = TRUE;
  rotate.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];

CAAnimation对象在图层上运行,因此对于Mac OS,您需要在界面构建器中设置“想要图层”属性,然后将动画添加到视图的图层。

要让您的视图永久旋转,您需要将重复次数设置为一些非常大的数字,例如1e100。

创建动画后,您可以使用以下代码将其添加到视图的图层中:

[myView.layer addAnimation: rotate forKey: @"rotateAnimation"];

这就是它的全部内容。

答案 1 :(得分:2)

更新

我最近了解到另一种处理大于180度旋转或连续旋转的方法。

有一个名为CAValueFunction的特殊对象,它允许您使用任意值对图层的变换应用更改,包括指定多个完整旋转的值。

您创建了图层变换属性的CABasicAnimation,但是然后您提供的值不是提供变换,而是提供新旋转角度的NSNumber。如果提供的角度为20pi,则图层将旋转10个完整旋转(2pi /旋转)。代码如下所示:

//Create a CABasicAnimation object to manage our rotation.
CABasicAnimation *rotation = [CABasicAnimation animationWithKeyPath:@"transform"];

rotation.duration = 10.0;
CGFLOAT angle = 20*M_PI;

//Set the ending value of the rotation to the new angle.
rotation.toValue = @(angle);

//Have the rotation use linear timing.
rotation.timingFunction = 
  [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];

/*
 This is the magic bit. We add a CAValueFunction that tells the CAAnimation we are 
 modifying the transform's rotation around the Z axis.
 Without this, we would supply a transform as the fromValue and toValue, and 
 for rotations > a half-turn, we could not control the rotation direction.

 By using a value function, we can specify arbitrary rotation amounts and 
 directions and even rotations greater than 360 degrees.
*/

rotation.valueFunction = 
  [CAValueFunction functionWithName: kCAValueFunctionRotateZ];



/*
 Set the layer's transform to it's final state before submitting the animation, so 
 it is in it's final state once the animation completes.
*/
imageViewToAnimate.layer.transform = 
  CATransform3DRotate(imageViewToAnimate.layer.transform, angle, 0, 0, 1.0);

[imageViewToAnimate.layer addAnimation:rotation forKey:@"transform.rotation.z"];

(我从一个工作示例应用程序中提取了上面的代码,并拿出了一些与主题没有直接关系的东西。你可以在github上的项目KeyframeViewAnimations(链接)中看到这个代码正在使用中执行旋转的代码位于名为`handleRotate'

的方法中