iOS制作 转盘EaseInEaseOut旋转动画

首先需要实现的是如图所示的一个转盘旋转动画,让此转盘最后指向的角度始终朝向正上方(初始指向随意,途中12个方向都是可以点击的)。

初始状态iOS制作 转盘EaseInEaseOut旋转动画_第1张图片        结束状态:iOS制作 转盘EaseInEaseOut旋转动画_第2张图片

做旋转效果一般有两种方案:

1.使用CoreAnimation

2.使用UIView封装的动画

第一种方案的缺陷是所有动画操作只是一个假象。最终动画结束以后还是会回到原来的位置或者状态,而如果使用removeOnCompletion属性虽然结束以后不会回到原来的状态,但是实际内部frame还是没有变化,(CoreAnimation动画可以看做,原图被隐藏,然后使用它的副本在做动画效果,最后如果设置了removeOnCompletion属性结果就是副本没有移除而已)。这样会导致一个很严重的后果就是点击button错乱,比如点击狮子按钮可能会发现双子那个按钮被点击了。

第二种方案也有一个很明显的缺陷,就是不能旋转超过360,设置transform为360度会发现根本不旋转。而如果采用隔一定时间旋转一个小角度来模拟旋转,那么慢-快-慢的这个整体效果就做不出来。

我的解决方案是采用CoreAnimation,在此之前还需要解决一个问题就是如何获得当前点击的方向的旋转角度。

首先这里的12个方向的button实际上是重叠在一块的朝正上方的12个button,然后一个个旋转30*i角度得到的。所以可以通过序号获得旋转过的角度,但是这里提供一个KVC的思路:

CGFloat angle=[[self.isSelectedButton valueForKeyPath:@"layer.transform.rotation"] floatValue];

因为在CoreAnimation中就是利用动画的KeyPath属性来决定是旋转动画还是平移动画等等。所以反过来利用keyPath得到一个transform过的图片的旋转角度。(如果图片一开始就有一个角度并不是通过transform过的 这个方法并不起作用)。

然后剩下的关键代码如下:(使用动画的代理的stop方法,将layer最后的位置强制设置到动画的toValue属性位置。采用CATransaction取消隐式动画)

- (IBAction)startR:(id)sender {
    
    CGFloat angle=[[self.isSelectedButton valueForKeyPath:@"layer.transform.rotation"] floatValue];
    CABasicAnimation* anim=[CABasicAnimation animation];
    anim.keyPath=@"transform.rotation";
    anim.toValue=@(M_PI*8 -angle);
    anim.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    anim.duration=2;
    
    anim.delegate=self;
    [self.luckyRotateWheel.layer addAnimation:anim forKey:nil];
    
}
(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
   CABasicAnimation* baseAnim=(CABasicAnimation*)aim;
   [CATransaction begin];
   [CATransaction setDisableActions:YES];
   [self.luckyRotateWheel setValue:baseAnim.toValue forKeyPath:@"layer.transform.rotation"];
   [CATransaction commit];
}


 参考网址: http://www.jianshu.com/p/18f1570d9660 
 

你可能感兴趣的:(iOS制作 转盘EaseInEaseOut旋转动画)