按钮动画的最佳方法是什么?

时间:2014-09-02 14:42:26

标签: ios iphone animation

我想在我的iPhone应用中制作一个类似于THIS图像

的滑出式菜单

对于菜单按钮,我想在按下与THIS几乎相同的菜单按钮时添加动画

我的问题是:执行动画的最佳方式是什么?

  1. 我是否创建了一个GIF图像,然后将GIF分解为单个图像,然后按下按钮以复制GIF时依次播放图像数组?
  2. 如下面的代码示例1中那样绘制菜单按钮的3行,当按下按钮时,我会像代码示例2中那样为行添加动画。 我可以在屏幕上绘制代表菜单图标的3行,然后在按下菜单按钮时,将顶部和底部线条移向中间线。当它们到达中间线时,移除其中一条线,然后将剩余的2条线旋转到+45和-45度以获得X外观
  3. *代码示例仅作为示例显示,而不是实际实现的代码

    代码示例1。

    UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, 200, self.view.bounds.size.width, 1)];
    lineView.backgroundColor = [UIColor blackColor];
    [self.view addSubview:lineView];
    [lineView release]; 
    

    代码示例2.

    +(void)rotateViewLikeCircle:(UIView*)view rotation:(int)numberOfRotation 
    {
        CABasicAnimation *rotationAnimation;
        rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
        rotationAnimation.toValue = [NSNumber numberWithFloat:DEGREES_TO_RADIANS(180)];
        rotationAnimation.duration = 0.75;
        rotationAnimation.repeatCount = numberOfRotation;
        rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
    
        [view.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
    }
    

1 个答案:

答案 0 :(得分:1)

我喜欢你的问题并开始研究你所描述的方法,并在此过程中学到了很多东西。我随函附上我的代码。但是在关闭动画的最后一部分中存在一个小问题。它略微抽搐,但它看起来像动画的一部分,考虑到按钮的大小很小,动画的持续时间非常少。

请告诉我,如果你可以在那个抽搐部分改进我的代码。

@interface YourViewController ()

@property (strong, nonatomic) CALayer *layer1;
@property (strong, nonatomic) CALayer *layer2;
@property (strong, nonatomic) CALayer *layer3;

@property (assign, nonatomic) BOOL isBtnStateOn;

@end

@implementation YourViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self createBtnSetup];
}

- (void)createBtnSetup
{
    self.layer1 = [self createLayerWithFrame:CGRectMake(40, 50, 60, 10)];
    self.layer2 = [self createLayerWithFrame:CGRectMake(40, 80, 60, 10)];
    self.layer3 = [self createLayerWithFrame:CGRectMake(40, 110, 60, 10)];

    // Place transparent button on top of layers.
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
    [btn setFrame:CGRectMake(40, 50, 60, 70)];
    [btn addTarget:self action:@selector(btnTapped:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];
}

- (CALayer *)createLayerWithFrame:(CGRect)frame
{
    CALayer *layer = [CALayer layer];
    [layer setFrame:frame];
    [layer setBackgroundColor:[UIColor blackColor].CGColor];
    [layer setCornerRadius:5.f];
    [layer setMasksToBounds:YES];
    [self.view.layer addSublayer:layer];

    return layer;
}

- (void)btnTapped:(id)sender
{
    if (self.isBtnStateOn == NO) {
        self.isBtnStateOn = YES;
        [self animateBtnToOnState];
    }
    else {
        self.isBtnStateOn = NO;
        [self animateBtnToOffState];
    }
}

- (void)animateBtnToOnState
{
    CABasicAnimation *translateAnim = [self getTranslationAnimationFrom:@(0) to:@(self.layer2.frame.origin.y - self.layer1.frame.origin.y) timingFunction:kCAMediaTimingFunctionEaseIn duration:0.5f beginTime:0.f fillMode:kCAFillModeForwards];
    [self.layer1 addAnimation:translateAnim forKey:@"translateAnimation"];

    translateAnim = [self getTranslationAnimationFrom:@(0) to:@(self.layer2.frame.origin.y - self.layer3.frame.origin.y) timingFunction:kCAMediaTimingFunctionEaseIn duration:0.5f beginTime:0.f fillMode:kCAFillModeForwards];
    [self.layer3 addAnimation:translateAnim forKey:@"translateAnimation"];

    CABasicAnimation *opacity = [self getOpacityAnimationFromValue:@(1.f) toValue:@(0.f) timingFunction:kCAMediaTimingFunctionLinear duration:0.f beginTime:0.4f fillMode:kCAFillModeForwards];
    [self.layer2 addAnimation:opacity forKey:@"opacityAnimation"];

    CABasicAnimation *rotation = [self getRotationAnimationWithFromAngle:@(0) toAngle:@(M_PI_2 + M_PI_4 + M_PI_4 / 5) timingFunction:kCAMediaTimingFunctionLinear duration:0.5f beginTime:0.5f fillMode:kCAFillModeForwards];
    [self.layer1 addAnimation:rotation forKey:@"rotationAnimation"];

    rotation = [self getRotationAnimationWithFromAngle:@(0) toAngle:@(M_PI_4) timingFunction:kCAMediaTimingFunctionLinear duration:0.5f beginTime:0.5f fillMode:kCAFillModeForwards];
    [self.layer3 addAnimation:rotation forKey:@"rotationAnimation"];

    CABasicAnimation *afterRotation = [self getRotationAnimationWithFromAngle:@(M_PI_2 + M_PI_4 + M_PI_4 / 5) toAngle:@(M_PI_2 + M_PI_4) timingFunction:kCAMediaTimingFunctionEaseIn duration:0.3f beginTime:1.f fillMode:kCAFillModeForwards];
    [self.layer1 addAnimation:afterRotation forKey:@"afterRotationAnimation"];
}

- (void)animateBtnToOffState
{
    CABasicAnimation *rotation = [self getRotationAnimationWithFromAngle:@(M_PI_2 + M_PI_4) toAngle:@(0) timingFunction:kCAMediaTimingFunctionEaseIn duration:0.5f beginTime:0.f fillMode:kCAFillModeForwards];
    [self.layer1 addAnimation:rotation forKey:@"rotationAnimation"];

    rotation = [self getRotationAnimationWithFromAngle:@(M_PI_4) toAngle:@(0) timingFunction:kCAMediaTimingFunctionEaseIn duration:0.5f beginTime:0.f fillMode:kCAFillModeForwards];
    [self.layer3 addAnimation:rotation forKey:@"rotationAnimation"];

    CABasicAnimation *opacity = [self getOpacityAnimationFromValue:@(0.f) toValue:@(1.f) timingFunction:kCAMediaTimingFunctionLinear duration:0.f beginTime:0.5f fillMode:kCAFillModeBackwards];
    [self.layer2 addAnimation:opacity forKey:@"opacityAnimation"];

    CABasicAnimation *translateAnim = [self getTranslationAnimationFrom:@(self.layer2.frame.origin.y - self.layer1.frame.origin.y) to:@(-0.25 * (self.layer2.frame.origin.y - self.layer1.frame.origin.y)) timingFunction:kCAMediaTimingFunctionEaseOut duration:0.5f beginTime:0.5f fillMode:kCAFillModeBackwards];
    [self.layer1 addAnimation:translateAnim forKey:@"translateAnimation"];

    translateAnim = [self getTranslationAnimationFrom:@(self.layer2.frame.origin.y - self.layer3.frame.origin.y) to:@(-0.25 * (self.layer2.frame.origin.y - self.layer3.frame.origin.y)) timingFunction:kCAMediaTimingFunctionEaseOut duration:0.5f beginTime:0.5f fillMode:kCAFillModeBackwards];
    [self.layer3 addAnimation:translateAnim forKey:@"translateAnimation"];
}

- (CABasicAnimation *)getTranslationAnimationFrom:(NSNumber *)fromValue to:(NSNumber *)toValue timingFunction:(NSString *)timingFunction duration:(CGFloat)duration beginTime:(CGFloat)beginTime fillMode:(NSString *)fillMode
{
    CABasicAnimation *translate = [self getBasicAnimationWithKeyPath:@"transform.translation.y" fromValue:fromValue toValue:toValue timingFunction:timingFunction duration:duration beginTime:beginTime fillMode:fillMode];
    return translate;
}

- (CABasicAnimation *)getRotationAnimationWithFromAngle:(NSNumber *)fromAngle toAngle:(NSNumber *)toAngle timingFunction:(NSString *)timingFunction duration:(CGFloat)duration beginTime:(CGFloat)beginTime fillMode:(NSString *)fillMode
{
    CABasicAnimation *rotation = [self getBasicAnimationWithKeyPath:@"transform.rotation.z" fromValue:fromAngle toValue:toAngle timingFunction:timingFunction duration:duration beginTime:beginTime fillMode:fillMode];
    return rotation;
}

- (CABasicAnimation *)getOpacityAnimationFromValue:(NSNumber *)fromValue toValue:(NSNumber *)toValue timingFunction:(NSString *)timingFunction duration:(CGFloat)duration beginTime:(CGFloat)beginTime fillMode:(NSString *)fillMode
{
    CABasicAnimation *opacity = [self getBasicAnimationWithKeyPath:@"opacity" fromValue:fromValue toValue:toValue timingFunction:timingFunction duration:duration beginTime:beginTime fillMode:fillMode];
    return opacity;
}

- (CABasicAnimation *)getBasicAnimationWithKeyPath:(NSString *)keyPath fromValue:(NSNumber *)fromValue toValue:(NSNumber *)toValue timingFunction:(NSString *)timingFunction duration:(CGFloat)duration beginTime:(CGFloat)beginTime fillMode:(NSString *)fillMode
{
    CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:keyPath];
    [basicAnimation setFromValue:fromValue];
    [basicAnimation setToValue:toValue];
    [basicAnimation setTimingFunction:[CAMediaTimingFunction functionWithName:timingFunction]];
    [basicAnimation setRepeatCount:0.f];
    [basicAnimation setDuration:duration];
    [basicAnimation setRemovedOnCompletion:NO];
    [basicAnimation setCumulative:YES];
    [basicAnimation setFillMode:fillMode];
    [basicAnimation setBeginTime:(CACurrentMediaTime() + beginTime)];
    return basicAnimation;
}

@end