按钮切换弹簧动画

CocoaChina上有一篇视错觉结合UI:从一个看似简单的自定义控件说起,实现了一个比较有趣的的控件,尝试用mask实现了类似的效果。
先看效果图:

按钮切换弹簧动画_第1张图片
效果图

思路

有两层view 后面一个放着五个黑色标题的按钮,上面一个view放着五个白色标题的按钮,给上层的view添加mask,mask大小就是选中的button的大小。
mask的简单理解:比如imageLayer有一个maskLayer作为mask, 如果maskLayer比imageLayer要小,那默认的maskLayer之外的地方都是透明的,都不会渲染。


按钮切换弹簧动画_第2张图片
tuceng.png

关键代码

1.创建的时候添加mask

    self.maskLayer = [CALayer layer];
    self.maskLayer.frame = CGRectMake(0, 0, width / titles.count, height);
    self.maskLayer.backgroundColor = [UIColor whiteColor].CGColor;
    self.maskLayer.cornerRadius = height * 0.25;
    self.showView.layer.mask = self.maskLayer;

2.mask的动画,position和bounds的变化

CGPoint position = CGPointMake(_lastButton.frame.origin.x + _lastButton.frame.size.width * 0.5, _lastButton.frame.origin.y + _lastButton.frame.size.height * 0.5);
    NSInteger num = fabs(sender.frame.origin.x - _lastButton.frame.origin.x) / sender.frame.size.width + 1;
    CGFloat x = MIN(sender.frame.origin.x, _lastButton.frame.origin.x);
    CGPoint fromPosition = CGPointMake(x + sender.frame.size.width * num * 0.5, position.y);
    CGPoint toPosition = CGPointMake(sender.frame.origin.x + sender.frame.size.width * 0.5, sender.frame.origin.y + sender.frame.size.height * 0.5);
    
    CAKeyframeAnimation *aniPos = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    aniPos.values = @[[NSValue valueWithCGPoint:CGPointMake(_lastButton.frame.origin.x + _lastButton.frame.size.width * 0.5, _lastButton.frame.origin.y + _lastButton.frame.size.height * 0.5)],[NSValue valueWithCGPoint:fromPosition],[NSValue valueWithCGPoint:toPosition]];
    
    CAKeyframeAnimation *aniBou = [CAKeyframeAnimation animationWithKeyPath:@"bounds"];
    aniBou.values = @[[NSValue valueWithCGRect:CGRectMake(0, 0, CGRectGetWidth(_lastButton.frame), CGRectGetHeight(_lastButton.frame))],[NSValue valueWithCGRect:CGRectMake(0, 0, CGRectGetWidth(sender.frame) * num, CGRectGetHeight(sender.frame))],[NSValue valueWithCGRect:CGRectMake(0, 0, CGRectGetWidth(sender.frame), CGRectGetHeight(sender.frame))]];
    
    CAAnimationGroup *anis = [CAAnimationGroup animation];
    anis.animations = @[aniBou,aniPos];
    anis.duration = 0.35;
    anis.removedOnCompletion = NO;
    anis.fillMode = kCAFillModeForwards;
    anis.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    [self.maskLayer addAnimation:anis forKey:nil];

完整demo:demo

你可能感兴趣的:(按钮切换弹簧动画)