核心动画,很早之前就想整理了,一直没整理,今天有时间,整理了下.官方文档是这么说的:下图就介绍了各个animation之间的关系
,官方文档中给了我们很多这个基础动画可以改变的属性,如下:
我自己整理了几个常用的属性
//CATransform3D Key Paths : (example)transform.rotation.z
//rotation.x
//rotation.y
//rotation.z
//rotation 旋轉
//scale.x
//scale.y
//scale.z
//scale 缩放
//translation.x
//translation.y
//translation.z
//translation 平移
//CGPoint Key Paths : (example)position.x
//x
//y
//CGRect Key Paths : (example)bounds.size.width
//origin.x
//origin.y
//origin
//size.width
//size.height
//size
//opacity
//backgroundColor
//cornerRadius
//borderWidth
//contents
//Shadow Key Path:
//shadowColor
//shadowOffset
//shadowOpacity
//shadowRadius
static NSString *position = @"position";
static NSString *opacity = @"opacity";
static NSString *transformX = @"transform.scale.x";
static NSString *backgroundColor = @"backgroundColor";
static NSString *transformY = @"transform.scale.y";
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self addSubview:self.mLabel];
[self addSubview:self.mButton];
CABasicAnimation *positionAni= [CABasicAnimation animationWithKeyPath:position];
positionAni.fromValue = @[@200,@70];
positionAni.toValue = @[@200,@200];
positionAni.duration = 2.f;
/*
Determines if the receiver’s presentation is frozen or removed once its active duration has completed.
动画周期完成后动画的状态,
/* `fillMode' options.
kCAFillModeForwards //forwards -----show(视觉上)
kCAFillModeBackwards //backwards-----remove(视觉上)
kCAFillModeBoth //show
kCAFillModeRemoved //default remove
*/
positionAni.fillMode = kCAFillModeForwards;
/* When true, the animation is removed from the render tree once its
* active duration has passed. Defaults to YES. 动画时间到了之后删除动画*/
positionAni.removedOnCompletion = NO;
// timingFunction:动画的时间节奏控制
/*
timingFunctionName的enum值如下:
kCAMediaTimingFunctionLinear 匀速
kCAMediaTimingFunctionEaseIn 慢进
kCAMediaTimingFunctionEaseOut 慢出
kCAMediaTimingFunctionEaseInEaseOut 慢进慢出
kCAMediaTimingFunctionDefault 默认值(慢进慢出)
*/
positionAni.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[_mLabel.layer addAnimation:positionAni forKey:position];
//backgroundColor //这里有一个坑,创建控件的时候不能设置背景色,不然没法通过这个属性改变动画了
CABasicAnimation *backAni = [CABasicAnimation animationWithKeyPath:backgroundColor];
backAni.fromValue = (__bridge id _Nullable)([[UIColor blueColor]CGColor]);
backAni.toValue = (__bridge id _Nullable)([[UIColor lightGrayColor] CGColor]);
backAni.fromValue = CFBridgingRelease([[UIColor blueColor] CGColor]);
backAni.toValue = CFBridgingRelease([[UIColor lightGrayColor] CGColor]);
backAni.removedOnCompletion = NO;
backAni.fillMode = kCAFillModeForwards;
backAni.duration = 2.f;
[_mLabel.layer addAnimation:backAni forKey:backgroundColor];
//opacity
CABasicAnimation *opacityAni = [CABasicAnimation animationWithKeyPath:opacity];
opacityAni.fromValue = @1.f;
opacityAni.toValue = @0.2f;
opacityAni.duration = 2.f;
opacityAni.removedOnCompletion = NO;
opacityAni.fillMode = kCAFillModeForwards;
[_mLabel.layer addAnimation:opacityAni forKey:opacity];
//transform____X 这个transform.scale.x的变化意思是控件宽的多少倍
CABasicAnimation *transAniX = [CABasicAnimation animationWithKeyPath:transformX];
transAniX.fromValue = @1;
transAniX.toValue = @1.5; //原控件宽的1.5倍放大
transAniX.duration = 2.f;
transAniX.removedOnCompletion = NO;
transAniX.fillMode = kCAFillModeForwards;
[_mLabel.layer addAnimation:transAniX forKey:transformX];
//transform____Y 这个transform.scale.x的变化意思是控件高的多少倍
CABasicAnimation *transAniY = [CABasicAnimation animationWithKeyPath:transformY];
transAniY.fromValue = @1;
transAniY.toValue = @2;//原控件高的2倍放大
transAniY.duration = 2.f;
transAniY.removedOnCompletion = NO;
transAniY.fillMode = kCAFillModeForwards;
[_mLabel.layer addAnimation:transAniY forKey:transformY];
//移除动画
[_mLabel.layer removeAllAnimations];
[_mLabel.layer removeAnimationForKey:opacity];
//values改变动画
CAKeyframeAnimation *keyframeAni = [CAKeyframeAnimation animationWithKeyPath:position];
keyframeAni.duration = 5.f;
NSValue *value1 = [NSValue valueWithCGPoint:CGPointMake(100, 200)];
NSValue *value2 = [NSValue valueWithCGPoint:CGPointMake(150, 200)];
NSValue *value3 = [NSValue valueWithCGPoint:CGPointMake(150, 300)];
NSValue *value4 = [NSValue valueWithCGPoint:CGPointMake(100, 300)];
NSValue *value5 = [NSValue valueWithCGPoint:CGPointMake(100, 200)];
NSArray *valueArr = @[value1,value2,value3,value4,value5];
keyframeAni.values = valueArr;
keyframeAni.fillMode = kCAFillModeForwards;
keyframeAni.removedOnCompletion = NO;
// [_mLabel.layer addAnimation:keyframeAni forKey:position];
//path改变动画
CAKeyframeAnimation *pathKeyframeAni = [CAKeyframeAnimation animationWithKeyPath:position];
pathKeyframeAni.duration = 5.f;
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddEllipseInRect(path, NULL, CGRectMake(140, 200, 100, 100));
pathKeyframeAni.path = path;
CGPathRelease(path);
pathKeyframeAni.removedOnCompletion = NO;
pathKeyframeAni.fillMode = kCAFillModeForwards;
// [_mLabel.layer addAnimation:pathKeyframeAni forKey:position];
//group 可以把几种动画放到一个数组中给group
CAAnimationGroup *group = [CAAnimationGroup animation];
group.animations = @[positionAni,opacityAni,backAni];
group.duration = 5.f;
group.fillMode = kCAFillModeForwards;
group.removedOnCompletion = NO;
group.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[_mLabel.layer addAnimation:group forKey:@""];
}
return self;
}
- (UILabel *)mLabel {
if (!_mLabel) {
_mLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 400, 150, 50)];
_mLabel.backgroundColor = [UIColor redColor];
_mLabel.text = @"This is a label";
_mLabel.userInteractionEnabled = YES;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(labelTapClick:)];
[_mLabel addGestureRecognizer:tap];
}
return _mLabel;
}
- (UIButton *)mButton {
if (!_mButton) {
_mButton = [UIButton buttonWithType:UIButtonTypeCustom];
_mButton.backgroundColor = [UIColor blueColor];
[_mButton setFrame:CGRectMake(30, 300, 59, 40)];
[_mButton setTitle:@"button" forState:UIControlStateNormal];
[_mButton addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _mButton;
}
- (UIImageView *)mImageView {
if (!_mImageView) {
_mImageView = [[UIImageView alloc] initWithFrame:CGRectMake(50, 100, 100, 50)];
[_mImageView setImage:[UIImage imageNamed:@"wade.jpg"]];
_mImageView.userInteractionEnabled = YES;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapClick:)];
[_mImageView addGestureRecognizer:tap];
}
return _mImageView;
}
#pragma mark === private func
- (void)btnClick:(UIButton *)sender {
CASpringAnimation *spring = [CASpringAnimation animationWithKeyPath:@"bounds"];
spring.toValue = [NSValue valueWithCGRect:CGRectMake(self.mButton.frame.origin.x, self.mButton.frame.origin.y, CGRectGetWidth(self.mButton.frame)*1.5, CGRectGetHeight(self.mButton.frame)*1.5)];
spring.mass = 10; //质量,影响图层运动时的弹簧惯性,质量越大,弹簧拉伸和压缩的幅度越大
spring.damping = 100; //阻尼系数,阻止弹簧伸缩的系数,阻尼系数越大,停止越快(刹车片)
spring.initialVelocity = 5;//开始的速率,速率为正,速度方向和运动方向一致,速率为负,相反
spring.stiffness = 5000; //刚度系数,刚度系数越大,形变产生的力就越大,运动越快
spring.duration = spring.settlingDuration;
[self.mButton.layer addAnimation:spring forKey:spring.keyPath];
}
- (void)tapClick:(UITapGestureRecognizer *)tap {
/* Common transition types.
kCATransitionFade
kCATransitionMoveIn
kCATransitionPush
kCATransitionReveal
*/
/* Common transition subtypes.
kCATransitionFromRight
kCATransitionFromLeft
kCATransitionFromTop
kCATransitionFromBottom
*/
/* //转场动画
CATransition *transition = [CATransition animation];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
transition.startProgress = 0.1;
transition.endProgress = 1.f;
transition.duration = 0.f; //导航跳转
transition.fillMode = kCAFillModeForwards;
transition.removedOnCompletion = NO;
_mImageView.image = [UIImage imageNamed:@"kb.jpg"];
[_mImageView.layer addAnimation:transition forKey:@"transition"];
*/
// 弹簧效果
CASpringAnimation *spring = [CASpringAnimation animationWithKeyPath:@"bounds"];
spring.toValue = [NSValue valueWithCGRect:CGRectMake(self.mImageView.frame.origin.x, self.mImageView.frame.origin.y, CGRectGetWidth(self.mImageView.frame)*1.5, CGRectGetHeight(self.mImageView.frame)*1.5)];
spring.mass = 10;
spring.damping = 100;
spring.initialVelocity = 5;
spring.stiffness = 5000;
spring.duration = spring.settlingDuration;
spring.removedOnCompletion = YES;
spring.fillMode = kCAFillModeBoth;
[self.mImageView.layer addAnimation:spring forKey:spring.keyPath];
}