使用CA进行动画制作时的圆形滑块怪异行为

时间:2013-07-17 08:35:36

标签: objective-c core-animation calayer

我想制作一个可拖动且可动画的圆形滑块。到目前为止,我已经设法构建滑块并使用拖动手柄移动它,甚至动画它。有时动画会出错(错误的方向或最短的方向。我已经将UIView(很快就会成为UIControl,只是想让动画首先正确)的子类增加了一个PanGestureRecognizer和几个图层。

enter image description here

那么我该如何解决这种奇怪的行为呢?我有人可以在这里帮助我,我会感激不尽:)

这是示例项目 - > http://cl.ly/2l0O3b1I3U0X

非常感谢!

编辑:

这是绘图代码:

CALayer *aLayer = [CALayer layer];
aLayer.bounds = CGRectMake(0, 0, 170, 170);
aLayer.position = self.center;
aLayer.transform = CATransform3DMakeRotation(M_PI_4, 0, 0, 1);

self.handleHostLayer = [CALayer layer];
self.handleHostLayer.bounds = CGRectMake(0, 0, 170, 170);
self.handleHostLayer.position = CGPointMake(CGRectGetMaxX(aLayer.bounds) - 170/2.0, CGRectGetMaxY(aLayer.bounds) - 170/2.0);

[aLayer addSublayer:self.handleHostLayer];
[self.layer addSublayer:aLayer];

self.handle = [CALayer layer];
self.handle.bounds = CGRectMake(0, 0, 50, 50);
self.handle.cornerRadius = 25;
self.handle.backgroundColor = [UIColor whiteColor].CGColor;
self.handle.masksToBounds = NO;
self.handle.shadowOffset = CGSizeMake(3.0, 0.0);
self.handle.shadowRadius = 0;
self.handle.shadowOpacity = .15;
self.handle.shadowColor = [UIColor blackColor].CGColor;

[self.handleHostLayer addSublayer:self.self.handle];

这是动画代码:

CGFloat handleTarget = ToRad(DEG);

CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
rotationAnimation.fromValue = @([[self.handleHostLayer valueForKeyPath:@"transform.rotation"] floatValue]);
rotationAnimation.toValue = @(handleTarget);
rotationAnimation.duration = .5;
rotationAnimation.removedOnCompletion = NO;
rotationAnimation.fillMode = kCAFillModeForwards;
rotationAnimation.cumulative = YES;
rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];

[self.handleHostLayer addAnimation:rotationAnimation forKey:@"transform.rotation"];

1 个答案:

答案 0 :(得分:1)

好的,我查看了你的项目。你的问题是,往返角度都不会落在0≤ɸ<2π范围内。

您可以通过添加和删除2π来确保它们完成,直到它们都在该范围内。

CGFloat fromAngle = [[self.handleHostLayer valueForKeyPath:@"transform.rotation"] floatValue];
CGFloat toAngle   = handleTarget;

while (fromAngle >= 2.0*M_PI) { fromAngle -= 2*M_PI; }
while (toAngle   >= 2.0*M_PI) { toAngle   -= 2*M_PI; }
while (fromAngle <  0.0)      { fromAngle += 2*M_PI; }
while (toAngle   <  0.0)      { toAngle   += 2*M_PI; }

CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
rotationAnimation.fromValue = @(fromAngle);
rotationAnimation.toValue   = @(toAngle);
// As before...

您可以改变的另一件事是滥用removeOnCompletion。我在this answer中做了很长的解释,说明为什么这样做很糟糕。

简而言之:由于您无意中引入了图层属性的值与您在屏幕上看到的内容之间的差异,因此您不会使用您认为自己动画的值进行动画制作。

一起跳过那条线。您也可以跳过跳过累积线,因为您没有重复动画。现在,如果你的动画没有坚持:在将动画添加到它之前将模型值设置为其最终值。