最近Github有一个上很火的开源动画集叫 Animations 。
我也很喜欢做动画动效,特来学习观摩。因为动效的特殊性,很多情况下这个项目里的动效不能直接Copy到我们现有的项目中直接使用,所以搞清楚她们的实现原理就很有必要了。建议配合源码学习。
没用过的POP的请移步 Facebook Pop 使用指南
效果如下
思路整体效果是用三个CAShapeLayer和一个UILabel组合实现的。CAShapeLayer负责绘制两个圆的边和一个实心圆。动画用POP的 POPBasicAnimation
和 POPSpringAnimation
。
你的肉眼能看出哪里用得哪种动画么?实心圆的尺寸变化、和空心圆的绘制进度是 POPBasicAnimation
实现的,基本是一个线性动画,匀速。实心圆的颜色改变用的是 POPSpringAnimation
弹簧动画。
CAShapeLayer
是一中特殊的CALayer用于绘制图形,可以理解成是CoreGraphic的一种对象化封装。一个CAShapeLayer可以绘制一个简单图形。例如例子里的圆
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.lineWidth + self.radius, self.lineWidth + self.radius) radius:self.radius + self.lineWidth / 2.f startAngle:self.startAngle endAngle:self.endAngle clockwise:self.clockWise]; shapeLayer.path = path.CGPath;
bezierPathWithArcCenter
这个方法中传入一系列参数,回忆了一条贝塞尔(bezier)曲线,分别是中心点、半径、开始角度、终止角度,是否闭环。
POP实现的文字动画,例子里用的同样是 POPBasicAnimation
,所以也是线性变化的。
- (void)pop_animationDidApply:(POPAnimation *)anim { NSLog(@"pop_animationDidApply %@", anim); NSValue *toValue = (NSValue *)[anim valueForKeyPath:@"currentValue"]; CGSize size = [toValue CGSizeValue]; [CATransaction setDisableActions:YES]; CGFloat percent = (size.height - _math.b) / _math.k; _circleShape1.strokeEnd = percent; _circleShape2.strokeEnd = percent; [CATransaction setDisableActions:NO]; UIColor *color = [UIColor colorWithRed:percent green:percent blue:percent alpha:1.f]; double showValue = fabs(percent * 100); self.label.text = [NSString stringWithFormat:@"%.f%%", showValue]; self.label.textColor = color; _blurImageView.alpha = 1 - percent; }
解释,这个POP动画的分帧回调,回调中用
NSValue *toValue = (NSValue *)[anim valueForKeyPath:@"currentValue"];
取得当前动画的值,这个动画实际只是改变了实心圆的尺寸。然后开发者通过当前尺寸计算出动画的进度
CGFloat percent = (size.height - _math.b) / _math.k;
CATransaction
动画开关,禁用了两个外边圆的 strokeEnd
隐式动画。
[CATransaction setDisableActions:YES];
Target模式,很容易理解。
// 按住按钮后没有松手的动画 [_button addTarget:self action:@selector(scaleToSmall) forControlEvents:UIControlEventTouchDown | UIControlEventTouchDragEnter]; // 按住按钮松手后的动画 [_button addTarget:self action:@selector(scaleAnimations) forControlEvents:UIControlEventTouchUpInside]; // 按住按钮后拖拽出去的动画 [_button addTarget:self action:@selector(scaleToDefault) forControlEvents:UIControlEventTouchDragExit];
高斯模糊(blur)的实现有很多方式,这个源码里使用的 UIImage+ImageEffects
是一个 UIImage
的扩展。
动画效果通过用blur层覆盖在普通层上,通过修改blur层alpha值实现。