2

我试图根据时间旋转具有各种子层的 CALayer。有 UDP 多播接收器将接收新的时间码。我通过计时器获取新时间:

 [NSTimer scheduledTimerWithTimeInterval:0.02f
 target:self
 selector:@selector(fetchNewTimeAndRotate)
 userInfo:nil
 repeats:YES];

CALayer 应该根据时间旋转。就我而言,1.8 秒内旋转一圈。其实我不需要任何动画,我只需要经常设置角度,以便它产生实际的动画。

我试过以各种方式设置图层旋转:

第一次我尝试通过 CATransform3DMakeRotation:

CATransform3D rotation1 = CATransform3DMakeRotation([self DegreesToRadians:newAngle], 0.0f, 0.0f, 1.0f);
self.circleLayer.transform=rotation1

第二次尝试是通过动画使用即时旋转:

rotation.fromValue = [NSNumber numberWithFloat:[self DegreesToRadians:oldAngle]];
rotation.toValue = [NSNumber numberWithFloat:[self DegreesToRadians:newAngle]];
rotation.duration = 0.0f;
rotation.repeatCount = 0.0f;
rotation.removedOnCompletion = NO; //also used YES here with no effect
[self.circleLayer addAnimation:rotation forKey:@"transform.rotation.z"];
oldAngle=newAngle;

第三次尝试只是为“transform.rotation.z”设置一个角度

[self.circleLayer setValue:[NSNumber numberWithFloat:[self DegreesToRadians:newAngle]] forKeyPath:@"transform.rotation.z"];

上述所有方法都有效,但会导致轮换出现明显的卡顿。我已经尝试在获取和动画长度中使用几种不同的时间。似乎没有什么能摆脱这个问题。使用每 0.02 次自转和 3.6° 角是唯一能为我呈现平滑结果的选项。我在这里犯了一个根本性的错误还是不理解 CoreAnimation 的概念?我知道它是用来制作动画本身的。但我需要它对用户输入做出反应并立即更改。我感谢任何帮助。

4

1 回答 1

0

你的意思是CADisplayLink,不是吗?

DisplayLink 对象通常用于 OpenGL 中基于帧的动画,但它们并不“使用 OpenGL”。创建显示链接并将其附加到您的应用程序以触发绘图是完全有效的。

正如另一位发帖人所说,NSTimer 不是精细控制动画帧的好选择。如果你编写一个程序,只运行一个计时器并测量它,它看起来会很好。但是,计时器取决于您的应用程序是否经常访问事件循环。它们不是抢占式的,如果您的应用程序在计时器应该触发时正忙,它将关闭,甚至错过触发间隔。

如果您继续使用显示链接,您可能需要编写代码来检查从最后一帧经过的时间,并以此计算动画量。这样,如果您丢弃一帧,动画仍然以正确的速度进行(如果您丢弃一帧,那么在下一帧之前经过两倍的时间,因此您使您的对象移动两倍。)

于 2012-12-04T01:56:33.240 回答