关键帧动画,动画组实现文字效果
程序员文章站
2022-03-25 23:37:38
...
拆分动画
实现一个动画,有很多种途径。不管是哪种途径,都要分析一下动画由哪几部分组成,然后将这些部分组合起来。
这是一个简单的动画,由两部分组成:
- 缩放动画,字体框架大小的缩放
- 旋转动画,字体放大到最大时,左右旋转,实现抖动效果
最后用动画组将这两组动画组合起来就OK了。
旋转动画
- (void)rotationAnimation {
CAKeyframeAnimation *rotationAnim = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];
// 动画时间
rotationAnim.duration =3.0;
//无限次重复
rotationAnim.repeatCount =MAXFLOAT;
// 保持最后的状态
rotationAnim.removedOnCompletion =NO;
//设置抖动数值
rotationAnim.values [email protected][@(ANGLE_TO_RADIAN(0)),@(ANGLE_TO_RADIAN(0)),@(ANGLE_TO_RADIAN(-7)),@(ANGLE_TO_RADIAN(7)),@(ANGLE_TO_RADIAN(0)),@(ANGLE_TO_RADIAN(0))];
rotationAnim.keyTimes = @[@(0), @(0.4), @(0.47), @(0.52), @(0.6), @(1.0)];
//动画的填充模式
rotationAnim.fillMode =kCAFillModeForwards;
//layer层实现动画
[self.searchLayer addAnimation:rotationAnim forKey:@"shake"];
}
缩放动画
- (void)scaleAnimation {
CAKeyframeAnimation *scaleAnim = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
scaleAnim.repeatCount = MAXFLOAT;
scaleAnim.duration = 3.0f;
scaleAnim.removedOnCompletion = NO;
scaleAnim.values = @[@(1.0),@(1.0), @(1.2), @(1.2),@(1.0),@(1.0)];
scaleAnim.keyTimes = @[@(0), @(0.2), @(0.3), @(0.7), @(0.8), @(1.0)];
scaleAnim.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
[self.searchLayer addAnimation:scaleAnim forKey:@"bouce"];
}
整体实现
分别实现之后,用动画组将他们组合起来。
效果上显示字体放大后执行旋转动画,这里我采用关键帧动画的keyTimes
来协调的。因为Apple并不建议在一个动画completion回调里执行另一个动画。
PS: 当这个button绑定的点击方法需要跳转VC时,可以设置动画组的 removedOnCompletion 属性为 NO 来让 VC 切换不停止动画。
//继承自UIButton
@interface ShakeButton : UIButton
@end
//
// ShakeButton.m
// HtmlLoad
//
// Created by zchao on 2018/3/21.
// Copyright © 2018年 zchao. All rights reserved.
//
#import "ShakeButton.h"
#define BoardWidth 2.0f
#define margin 8.0f
#define ANGLE_TO_RADIAN(angle) ((angle)/180.0 * M_PI)
@interface ShakeButton ()
@property(nonatomic, strong) CALayer *searchLayer;
@end
@implementation ShakeButton
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
//添加图层到根图层
CGFloat x = (2-sqrtf(2))*0.25 * frame.size.width + 0.5*sqrtf(2)*BoardWidth;
CGFloat width = sqrt(2)*0.5*frame.size.width - sqrtf(2)*BoardWidth;
[self.layer addSublayer:[self drawSearchLayer:CGRectMake(x, x, width, width)]];
[self startAnimation];
// [self scaleAnimation];
// [self rotationAnimation];
}
return self;
}
- (void)startAnimation {
CAKeyframeAnimation *rotationAnim = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];
// 动画时间
rotationAnim.duration =3.0;
//无限次重复
rotationAnim.repeatCount =MAXFLOAT;
// 保持最后的状态
rotationAnim.removedOnCompletion =NO;
//设置抖动数值
rotationAnim.values [email protected][@(ANGLE_TO_RADIAN(0)),@(ANGLE_TO_RADIAN(0)),@(ANGLE_TO_RADIAN(-7)),@(ANGLE_TO_RADIAN(7)),@(ANGLE_TO_RADIAN(0)),@(ANGLE_TO_RADIAN(0))];
rotationAnim.keyTimes = @[@(0), @(0.4), @(0.47), @(0.52), @(0.6), @(1.0)];
//动画的填充模式
rotationAnim.fillMode =kCAFillModeForwards;
CAKeyframeAnimation *scaleAnim = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
scaleAnim.repeatCount = MAXFLOAT;
scaleAnim.duration = 3.0f;
scaleAnim.removedOnCompletion = NO;
scaleAnim.values = @[@(1.0),@(1.0), @(1.2), @(1.2),@(1.0),@(1.0)];
scaleAnim.keyTimes = @[@(0), @(0.2), @(0.3), @(0.7), @(0.8), @(1.0)];
scaleAnim.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
CAAnimationGroup *group = [CAAnimationGroup animation];
group.duration = 3.0f;
group.repeatCount = MAXFLOAT;
group.animations = @[rotationAnim, scaleAnim];
group.removedOnCompletion = NO;
[self.searchLayer addAnimation:group forKey:@"fuck"];
}
- (void)scaleAnimation {
CAKeyframeAnimation *scaleAnim = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
scaleAnim.repeatCount = MAXFLOAT;
scaleAnim.duration = 3.0f;
scaleAnim.removedOnCompletion = NO;
scaleAnim.values = @[@(1.0),@(1.0), @(1.2), @(1.2),@(1.0),@(1.0)];
scaleAnim.keyTimes = @[@(0), @(0.2), @(0.3), @(0.7), @(0.8), @(1.0)];
scaleAnim.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
[self.searchLayer addAnimation:scaleAnim forKey:@"bouce"];
}
- (void)rotationAnimation {
CAKeyframeAnimation *rotationAnim = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];
// 动画时间
rotationAnim.duration =3.0;
//无限次重复
rotationAnim.repeatCount =MAXFLOAT;
// 保持最后的状态
rotationAnim.removedOnCompletion =NO;
//设置抖动数值
rotationAnim.values [email protected][@(ANGLE_TO_RADIAN(0)),@(ANGLE_TO_RADIAN(0)),@(ANGLE_TO_RADIAN(-7)),@(ANGLE_TO_RADIAN(7)),@(ANGLE_TO_RADIAN(0)),@(ANGLE_TO_RADIAN(0))];
rotationAnim.keyTimes = @[@(0), @(0.4), @(0.47), @(0.52), @(0.6), @(1.0)];
//动画的填充模式
rotationAnim.fillMode =kCAFillModeForwards;
//layer层实现动画
[self.searchLayer addAnimation:rotationAnim forKey:@"shake"];
}
//Only override drawRect: if you perform custom drawing. An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
//Drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextAddArc(context, rect.size.width/2, rect.size.height/2, rect.size.width/2-BoardWidth, 0, 2*M_PI, 0);
CGPoint aPoints[2];
aPoints[0] =CGPointMake(rect.size.width*(0.5+sqrtf(2)/4), rect.size.width*(0.5+sqrtf(2)/4));
aPoints[1] =CGPointMake(rect.size.width, rect.size.height);
CGContextAddLines(context, aPoints, 2);
//画笔颜色
CGContextSetRGBStrokeColor(context, 1, 1, 1, 1.0);
//线条粗细
CGContextSetLineWidth(context, BoardWidth);
CGContextDrawPath(context, kCGPathStroke);
}
- (CALayer *)drawSearchLayer:(CGRect)rect {
//自定义图层
CATextLayer *layer = [[CATextLayer alloc] init];
self.searchLayer = layer;
layer.frame = rect;
layer.foregroundColor = RGBACOLOR(255, 184, 62, 1).CGColor;
layer.string = @"搜";
UIFont *font = [UIFont boldSystemFontOfSize:11];
CFStringRef fontName = (__bridge CFStringRef)font.fontName;
CGFontRef fontRef =CGFontCreateWithFontName(fontName);
layer.font = fontRef;
layer.fontSize = font.pointSize;
CGFontRelease(fontRef);
layer.contentsScale = [UIScreen mainScreen].scale;
layer.alignmentMode = kCAAlignmentCenter;
return layer;
}
@end
上一篇: 详解JavaScript的垃圾回收机制
下一篇: 四十二、ETL工具Kettle的转换步骤