谷歌翻译TabBar点击效果动画复刻

项目名称:WWAnimationTabbar

项目地址:https://github.com/WilliamZhangWH/WWAnimationTabbar

效果展示

image

调用方法

increasedHeight为0即为系统TabBar高度

1
- (instancetype)initWithFrame:(CGRect)frame increasedHeight:(CGFloat)height;

代理方法

记录从哪里跳转到哪里

1
- (void)tabBar:(WWTabBar *)tabBar selectedFrom:(NSInteger)from to:(NSInteger)to;

按钮点击圆形扩展动画原理

原理:创建CAShapeLayer图层,通过UIBezierPath创建两个绘图路径,再通过CABasicAnimation完成两个绘图路径之间动画转变

图层创建>>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- (CAShapeLayer *)circlePathLayer     {
if (!_circlePathLayer) {
_circlePathLayer = [[CAShapeLayer alloc]init];
_circlePathLayer.frame = self.bounds;

CGRect circleFrame = CGRectMake(0, 0, circleRadius, circleRadius);
circleFrame.origin.x = CGRectGetMidX(_circlePathLayer.bounds);
circleFrame.origin.y = CGRectGetMidY(_circlePathLayer.bounds);
self.circleFrame = circleFrame;

_circlePathLayer.path = [self getSmallCirclePath].CGPath;


self.layer.masksToBounds = YES;
_circlePathLayer.fillColor = Shadow_Color.CGColor;
_circlePathLayer.backgroundColor= [UIColor clearColor].CGColor;

/* 添加到按钮的第一层 这样不会覆盖按钮的Image * /
[self.layer insertSublayer:_circlePathLayer atIndex:0];
}

return _circlePathLayer;
}

绘图路径创建 (需要创建两个路径,第一个是点击时候出现的一个小圆,第二个是覆盖整个按钮的一个大圆)

小圆路径创建

1
2
3
4
- (UIBezierPath *)getSmallCirclePath {
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.circleFrame.origin.x, self.circleFrame.origin.y) radius:circleRadius startAngle:0.0 endAngle:M_PI*2 clockwise:YES];

return path;
}

大圆路径创建

1
2
3
4
5
6
7
8
- (UIBezierPath *)getBigCirclePath {
/* 求按钮对角线的距离 即为大圆的半径 这样不论点击按钮的任何位置大圆都可完全覆盖 */
/* 函数功能:已知直角三角形的两个直角边,求斜边*/
CGFloat bigCircleRadius = hypotf(self.bounds.size.width, self.bounds.size.height);

UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.circleFrame.origin.x, self.circleFrame.origin.y) radius:bigCircleRadius startAngle:0.0 endAngle:M_PI*2 clockwise:YES];
return path;
}

小圆到大圆的扩张动画

1
2
3
4
5
6
7
8
9
- (void)pathExpandAnimate {
CABasicAnimation *circleAnimtion = [CABasicAnimation animationWithKeyPath:@"path"];
circleAnimtion.removedOnCompletion = NO;
circleAnimtion.duration = 0.3;
circleAnimtion.fromValue = (__bridge id)[self getSmallCirclePath].CGPath;
circleAnimtion.toValue = (__bridge id)[self getBigCirclePath].CGPath;
_circlePathLayer.path = [self getBigCirclePath].CGPath;
[_circlePathLayer addAnimation:circleAnimtion forKey:@"animPath"];
}

通过按钮的触摸事件来触发动画的开始和结束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
   - (void)showCircleLayerWithPoint:(CGPoint)position {
[self circlePathLayer];
/* 传递手指点击的位置 */
self.circlePathLayer.position = position;
[self pathExpandAnimate];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
/* 执行按钮的事件方法 不写不会执行 */
[self sendActionsForControlEvents:UIControlEventTouchDown];
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];

[self showCircleLayerWithPoint:point];
}

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[_circlePathLayer removeFromSuperlayer];
_circlePathLayer = nil;
}
参考文档

http://www.07net01.com/2015/07/874188.html

如果有不明白的地方可以给我留言。欢迎交流!