【问题标题】:Can´t get a smooth step by step rotation with CoreAnimation and CALayers无法使用 CoreAnimation 和 CALayers 进行平滑的逐步旋转
【发布时间】:2012-12-03 10:22:58
【问题描述】:

我正在尝试根据时间旋转具有各种子层的 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 的概念?我知道它是用来制作动画本身的。但我需要它对用户输入做出反应并立即更改。 感谢您的帮助。

【问题讨论】:

  • 圆形图层是您创建的图层还是您的某个视图的图层?

标签: objective-c xcode core-animation calayer


【解决方案1】:

您的意思是 CADisplayLink,对吗?

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

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

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

【讨论】:

  • 首先,谢谢。我认为 CADisplayLink 仅适用于 iPhone。我正在编写一个 OS.X 应用程序,所以我需要使用使用 OpenGL 的 CVDisplayLink。有没有办法将 CADisplayLink 与 OS.X 应用程序一起使用?我很想试试。 CVDispayLink 正在创建一个高优先级线程,当显示器准备好重绘时,OpenGL 会通知该线程。所以我必须进入线程,我真的想避免(对于旋转的圆盘来说可能有点多,我不知道)。我知道 NSTimer 现在可能不准确,但我认为只要不在其他地方使用处理时间,它就可以完成工作。
  • 枪子,我猜你是对的。几乎所有的 CA 类都是跨平台的,所以我认为 CADisplayLink 也是。我的错。如果您要做的只是一个旋转的磁盘,为什么不在旋转属性上使用 UIView 块动画,间隔较长,如 1/10 秒,您从前一个值旋转到目的地每个间隔的值,以及线性时间?由于每一步都是动画,因此速度和目的地位置的变化应该非常微妙。
  • 好的,我正在做的事情如下:我通过网络获取时间码并且必须相应地旋转。由于用户输入,需要尽可能频繁地更新光盘。 1/10 秒远远不够,用户输入可以更快地到来。我唯一能想到的就是放弃 CALayers 并改用 OpenGL。自己编写代码似乎是正确的做法
  • 我现在开始工作了,我使用 CVDisplayLink 来触发所有 CALayers 的重绘。处理线程部分有点棘手,但我让它工作了。非常感谢 Duncan 和 David 的支持。 CVDisplayLink 是要走的路!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-22
相关资源
最近更新 更多