iOS之核心动画
.将动画的所有方法封装到一个类里面 MyCAHelper.h
#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h> #define kCAHelperAlphaAnimation @"opacity"; // 淡入淡出动画
#define kCAHelperScaleAnimation @"transform.scale"; // 比例缩放动画
#define kCAHelperRotationAnimation @"transform.rotation"; // 旋转动画
#define kCAHelperPositionAnimation @"position"; // 平移位置动画 @interface MyCAHelper : NSObject #pragma mark - 基本动画统一调用方法
+ (CABasicAnimation *)myBasicAnimationWithType:(NSString *)animationType
duration:(CFTimeInterval)duration
from:(NSValue *)from
to:(NSValue *)to
autoRevereses:(BOOL)autoRevereses; #pragma mark - 关键帧动画方法
#pragma mark 摇晃动画
+ (CAKeyframeAnimation *)myKeyShakeAnimationWithDuration:(CFTimeInterval)duration
angle:(CGFloat)angle
repeatCount:(CGFloat)repeatCount; #pragma mark 贝塞尔路径动画
+ (CAKeyframeAnimation *)myKeyPathAnimationWithDuration:(CFTimeInterval)duration
path:(UIBezierPath *)path; #pragma mark 弹力仿真动画
+ (CAKeyframeAnimation *)myKeyBounceAnimationFrom:(CGPoint)from
to:(CGPoint)to
duration:(CFTimeInterval)duration; @end
MyCAHelper.m
#import "MyCAHelper.h" @implementation MyCAHelper #pragma mark - 基本动画统一调用方法
+ (CABasicAnimation *)myBasicAnimationWithType:(NSString *)animationType
duration:(CFTimeInterval)duration
from:(NSValue *)from
to:(NSValue *)to
autoRevereses:(BOOL)autoRevereses
{
// 1. 实例化一个CA动画对象
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:animationType]; // 2. 设置动画属性
[anim setDuration:duration]; [anim setFromValue:from];
[anim setToValue:to]; [anim setAutoreverses:autoRevereses]; return anim;
} #pragma mark - 关键帧动画方法
#pragma mark 摇晃动画
+ (CAKeyframeAnimation *)myKeyShakeAnimationWithDuration:(CFTimeInterval)duration
angle:(CGFloat)angle
repeatCount:(CGFloat)repeatCount
{
// 1. 初始化动画对象实例
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"]; // 2. 设置动画属性
[anim setDuration:duration]; [anim setValues:@[@(angle), @(-angle), @(angle)]]; [anim setRepeatCount:repeatCount]; return anim;
} #pragma mark 贝塞尔路径动画
+ (CAKeyframeAnimation *)myKeyPathAnimationWithDuration:(CFTimeInterval)duration
path:(UIBezierPath *)path
{
// 1. 初始化动画对象实例
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"]; // 2. 设置动画属性
[anim setDuration:duration]; [anim setPath:path.CGPath]; return anim;
} #pragma mark 弹力仿真动画
+ (CAKeyframeAnimation *)myKeyBounceAnimationFrom:(CGPoint)from
to:(CGPoint)to
duration:(CFTimeInterval)duration
{
// 是一个基于路径的动画
// 首先定义一个路径,记录弹力仿真的整个路径
CGMutablePathRef path = CGPathCreateMutable(); // 弹力仿真路径创建代码
// 计算起始点与目标点之间的位置偏移量,这个偏移量的目的是为了能够计算出小球第一次延伸的长度
CGFloat offsetX = from.x - to.x;
CGFloat offsetY = from.y - to.y; // 1. 移动到起始点
CGPathMoveToPoint(path, NULL, from.x, from.y);
// 2. 将目标点的坐标添加到路径之中
CGPathAddLineToPoint(path, NULL, to.x, to.y);
// 3. 设置小球的弹力因子
CGFloat offsetDivider = 4.0f; while (YES) {
// 加延伸方向的路径
CGPathAddLineToPoint(path, NULL, to.x + offsetX / offsetDivider,
to.y + offsetY / offsetDivider); // 再次将目标点添加到路径
CGPathAddLineToPoint(path, NULL, to.x, to.y); // 弹力因子递增,保证越来越接近目标点
offsetDivider += 6.0f; // 当小球的当前位置距离目标点足够小,我们退出循环
if ((abs(offsetX / offsetDivider) < 10.0f)
&& (abs(offsetY / offsetDivider) < 10.0f)) { break;
}
} CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
[anim setPath:path]; // 释放路径
CGPathRelease(path); [anim setDuration:duration]; return anim;
} @end
#import "ViewController.h"
#import "MyCAHelper.h" @interface ViewController ()
{
UIView *_demoView;
CGPoint location;
}
@end @implementation ViewController - (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.view setBackgroundColor:[UIColor lightGrayColor]]; _demoView = [[UIView alloc]initWithFrame:CGRectMake(, , , )];
[_demoView setBackgroundColor:[UIColor whiteColor]];
[self.view addSubview:_demoView];
} - (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
location = [touch locationInView:self.view]; // [_demoView setCenter:location];
/**
1.测试基本动画
*/
// CABasicAnimation *anim = [self testBasic1];
// [anim setRepeatCount:3];
//
// [_demoView.layer addAnimation:anim forKey:nil];
/**
2.测试弹力仿真动画效果
*/
// [_demoView.layer addAnimation:[self test1:_demoView.center to:location] forKey:nil];
/**
3.测试路径关键帧动画
*/
// [_demoView.layer addAnimation:[self test2] forKey:nil];
// [_demoView.layer addAnimation:[self test4:_demoView.center to:location] forKey:nil];
/**
4.测试摇晃关键帧动画
*/
// 点击屏幕,开始摇晃,再次点击,停止摇晃
// CAAnimation *anim = [_demoView.layer animationForKey:@"shakeAnimation"];
// if (anim) {
// [_demoView.layer removeAnimationForKey:@"shakeAnimation"];
// } else {
// [_demoView.layer addAnimation:[self test5] forKey:@"shakeAnimation"];
// }
CAKeyframeAnimation *anim = [self test1:_demoView.center to:location];
[_demoView.layer addAnimation:anim forKey:nil];
}
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
// 需要在这里对不同对象的动画方法进行完成处理!
[_demoView setCenter:location];
NSLog(@"%@", NSStringFromCGPoint(_demoView.center));
} #pragma mark - 重构方法测试
#pragma mark 测试贝塞尔路径关键帧动画
- (CAKeyframeAnimation *)test5
{
return [MyCAHelper myKeyShakeAnimationWithDuration:0.2 angle:M_PI_4 / repeatCount:MAXFLOAT];
} #pragma mark 测试贝塞尔路径关键帧动画
- (CAKeyframeAnimation *)test4:(CGPoint)from to:(CGPoint)to
{
UIBezierPath *path = [UIBezierPath bezierPath]; // 有两个控制点去挤出的曲线,能挤出S型的曲线
[path moveToPoint:from];
[path addCurveToPoint:to controlPoint1:CGPointMake(, ) controlPoint2:CGPointMake(, )]; return [MyCAHelper myKeyPathAnimationWithDuration:2.0 path:path];
} #pragma mark 测试贝塞尔路径关键帧动画
- (CAKeyframeAnimation *)test3:(CGPoint)from to:(CGPoint)to
{
UIBezierPath *path = [UIBezierPath bezierPath]; // 只有一个控制点去挤出的曲线
[path moveToPoint:from];
[path addQuadCurveToPoint:to controlPoint:CGPointMake(, )]; return [MyCAHelper myKeyPathAnimationWithDuration:2.0 path:path];
} #pragma mark 测试路径关键帧动画
- (CAKeyframeAnimation *)test2
{
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(, , , )];
return [MyCAHelper myKeyPathAnimationWithDuration:2.0 path:path];
} #pragma mark 测试弹力仿真动画效果
- (CAKeyframeAnimation *)test1:(CGPoint)from to:(CGPoint)to
{
CAKeyframeAnimation *anim = [MyCAHelper myKeyBounceAnimationFrom:from to:to duration:1.5];
[anim setFillMode:kCAFillModeForwards];
[anim setRemovedOnCompletion:NO]; [anim setDelegate:self]; return anim;
} - (CABasicAnimation *)testBasic1
{
return [MyCAHelper myBasicAnimationWithType:@"opacity" duration:1.0 from:@(1.0) to:@(0.3) autoRevereses:YES];
} @end
一、核心动画概念
-导入QuartzCore.framework框架
1⃣ 开发步骤
1.初始化一个动画对象(CAAnimation)并且设置一些动画相关属性
2.CALayer中很多属性都可以通过CAAnimation实现动画效果,包括:opacity、position、transform、bounds、contents等(可以在API文档中搜索:CALayer Animatable Properties)
3.添加动画对象到层(CALayer)中,开始执行动画
4.通过调用CALayer的addAnimation:forKey增加动画到层(CALayer)中,这样就能触发动画。通过调用removeAnimationForKey可以停止层中的动画
5.Core Animation的动画执行过程都是后台操作的,不会阻塞主线程
2⃣ 属性
1.duration:动画的持续时间
2.repeatCount:重复次数(HUGE_VALF、MAX FLOAT无限重复)
3.repeatDuration:重复时间(用的很少)
4.removedOnCompletion:默认为Yes。动画执行完后默认会从图层删除掉
5.fillMode
6.biginTime
7.timingFunction:速度控制函数,控制动画节奏
8.delegate
二、基础动画(CABasicAnimation)
如果只是实现简单属性变化的动画效果,可以使用UIView的块动画替代基本动画
1⃣ 属性说明
-fromValue:keyPath相应属性值的初始值
-toValue:keyPath相应属性的结束值
2⃣ 动画过程说明:
-随着动画的就行,在duration的持续时间内,keyPath相应的属性值从fromValue渐渐变为toValue
-keyPath内容是CALayer的可动画Animation属性
-如果fillMode=kCAFillModeForwards同时removedOnCompletion=NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态,但在实质上,图层的属性值还是动画执行前的初始值,并没有真正改变
3⃣ 代码实现
位移需要考虑目标点设定的问题
三、关键帧动画(CAKeyframeAnimation)
基础动画只能从一个值到另一个值,关键帧动画可以用一个数组保存一系列值
1⃣ 属性说明
-values:所有的值(用的较少)
-path:路线(如果设置了path,那么values将被忽略)
-keyTimes:可以为对应的关键帧制定对应的时间点,取值范围是0到1.0
2⃣ 过程步骤
-初始化自定义视图
-点击屏幕,执行动画
1.指定点平移动画(values)
2.路径平移动画(path C语言框架CGMutablePathRef,需要手动释放内存)
3.贝塞尔路径动画(OC框架UIBezierPath)
4.摇晃动画(修改旋转角度)
3⃣ 代码重构
如上代码,重构在了一起
四、动画组
动画是可以并发执行的
-定义一个group组
-定义动画
-将动画加入group组
-可以给组设置属性
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self.view]; [_demoView setBackgroundColor:[UIColor redColor]]; // 1. 定义动画组
CAAnimationGroup *group = [CAAnimationGroup animation];
// 定义一组动画
// 淡入淡出动画
CABasicAnimation *alpha = [MyCAHelper myBasicAnimationWithType:kCAHelperAlphaAnimation duration:1.0 from:@(1.0) to:@(0.3) autoRevereses:YES];
// 旋转动画
CABasicAnimation *rotation = [MyCAHelper myBasicAnimationWithType:kCAHelperRotationAnimation duration:2.0 from:@(-M_PI_2) to:@(M_PI_2) autoRevereses:NO];
// 缩放动画
CABasicAnimation *scale = [MyCAHelper myBasicAnimationWithType:kCAHelperScaleAnimation duration:0.5 from:@(1.0) to:@(0.1) autoRevereses:YES]; // 关键帧路径动画,弹力仿真动画效果
CAKeyframeAnimation *path = [self test1:_demoView.center to:location]; // 2. 设置动画组属性
[group setAnimations:@[alpha, path, rotation, scale]]; // 设置动画的时长
[group setDuration:4.0]; // 3. 将动画组添加到图层
[_demoView.layer addAnimation:group forKey:nil];
}
五、转场动画-CATransition
1⃣属性说明
-type:动画过渡类型
-subtype:动画过渡方向
-startProgress:动画起点(在整体动画的百分比)
-endProgress:动画终点(在整体动画的百分比)
-增加一个转场演示视图
-增加轻扫手势
-在轻扫手势方法中
1.更改演示视图内容
2.创建转场动画效果
3.将转场动画添加到视图的图层
// 轻扫手势操作
- (void)swipeAction:(UISwipeGestureRecognizer *)sender
{
// 通过轻扫手势,让切换出来的视图是蓝色的
if (_demoView.tag == ) {
[_demoView setBackgroundColor:[UIColor blueColor]];
[_demoView setTag:];
}
else
{
[_demoView setBackgroundColor:[UIColor redColor]];
[_demoView setTag:];
} // 根据视图内容我们来实现专场动画
CATransition *anim = [CATransition animation];
// 设置专场动画的过渡类型
[anim setType:@"cameraIrisHollowClose"];
// 需要根据手势的方向,来决定专场动画的动画方向
// 注意:在转场动画中,动画方向的左右是和手势的方向相反的
if (sender.direction == UISwipeGestureRecognizerDirectionLeft) {
[anim setSubtype:kCATransitionFromRight];
} else {
[anim setSubtype:kCATransitionFromLeft];
} [_demoView.layer addAnimation:anim forKey:nil];
} - (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// 1. 实例化自定义视图
_demoView = [[UIView alloc]initWithFrame:self.view.bounds];
[_demoView setBackgroundColor:[UIColor redColor]]; [self.view addSubview:_demoView]; // 2. 增加轻扫手势
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc]
initWithTarget:self
action:@selector(swipeAction:)];
[swipeLeft setDirection:UISwipeGestureRecognizerDirectionLeft];
[_demoView addGestureRecognizer:swipeLeft]; UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc]
initWithTarget:self
action:@selector(swipeAction:)];
[swipeRight setDirection:UISwipeGestureRecognizerDirectionRight];
[_demoView addGestureRecognizer:swipeRight];
}
六、UIView的转场动画-双视图
+(void)transitionWithView:(UIView*)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void(^)(void))animations completion:(void(^)(BOOL finished))completion; ⃣参数说明
-duration:动画的持续时间 -view:需要进行转场动画的视图 -options:转场动画的类型 -animations:将改变视图属性的代码放在这个Block里 -completion:动画结束后,自动调用的Block @interface ViewController ()
{
UIImageView *_demoImageView;
UIImageView *_demoImageView2;
}
@end @implementation ViewController - (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// 实例化第一个UIImageView的对象
_demoImageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"1.jpg"]];
[self.view addSubview:_demoImageView]; // 实例化第二个UIImageView对象
// 注意:在双视图转场动画中,不要将第二个视图添加到主视图
_demoImageView2 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"2.jpg"]];
} - (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 单击屏幕的时候,实现转场动画效果
[self animation1];
} #pragma mark - 单视图的转场动画
- (void)animation2
{
UIImageView *from;
UIImageView *to; if (_demoImageView.superview) {
from = _demoImageView;
to = _demoImageView2;
}
else
{
from = _demoImageView2;
to = _demoImageView;
} [UIView transitionFromView:from toView:to duration:1.0f options:UIViewAnimationOptionTransitionCrossDissolve completion:^(BOOL finished) {
NSLog(@"image view1 的主视图: %@", _demoImageView.superview);
NSLog(@"image view2 的主视图: %@", _demoImageView2.superview);
}];
} #pragma mark - 单视图的转场动画
- (void)animation1
{
[UIView transitionWithView:_demoImageView duration:1.0f options:UIViewAnimationOptionTransitionCurlUp animations:^{
// 在动画块代码中设置视图内容变化
if (_demoImageView.tag == ) {
[_demoImageView setImage:[UIImage imageNamed:@"2.jpg"]];
[_demoImageView setTag:];
}
else
{
[_demoImageView setImage:[UIImage imageNamed:@"1.jpg"]];
[_demoImageView setTag:];
}
} completion:nil];
}
iOS之核心动画的更多相关文章
- IOS QuartzCore核心动画框架
IOS QuartzCore核心动画框架 核心动画框架 使用核心动画需要引入的框架:#import CALayer: CoreAnimation CALayer就是UIView上的图层,很多的CALa ...
- iOS学习——核心动画
iOS学习——核心动画 1.什么是核心动画 Core Animation(核心动画)是一组功能强大.效果华丽的动画API,无论在iOS系统或者在你开发的App中,都有大量应用.核心动画所在的位置如下图 ...
- iOS学习——核心动画之Layer基础
iOS学习——核心动画之Layer基础 1.CALayer是什么? CALayer我们又称它叫做层.在每个UIView内部都有一个layer这样一个属性,UIView之所以能够显示,就是因为它里面有这 ...
- iOS:核心动画的详解介绍:CAAnimation(抽象类)及其子类
核心动画的详解介绍:CAAnimation(抽象类) 1.核心动画基本概念 Core Animation是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍! 使用它 ...
- iOS之核心动画(Core Animation)
Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍.也就是说,使用少量的代码就可以实现非常强大的功能. Core ...
- iOS基础 - 核心动画
一.核心动画 l 核心动画基本概念 l 基本动画 l 关键帧动画 l 动画组 l 转场动画 l Core Animation是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事 ...
- iOS:核心动画之基本动画CABasicAnimation
基本动画,是CAPropertyAnimation的子类 属性说明: fromValue:keyPath相应属性的初始值 toValue:keyPath相应属性的结束值 动画过程说明: 随着动画的进行 ...
- iOS:核心动画具体的类和协议的介绍
核心动画类:CAAnimation.CAPropertyAnimation.CABasicAnimation.CAKeyframeAnimation.CATransition.CAAnimationG ...
- iOS开发-核心动画随笔
核心动画可以让View旋转,缩放,平移(主要是操作View的layer(层)属性)但是核心动画改变的位置不是真实的位置,一切都是假象所以有时候要用到其他动画,如UIView本来封装的动画,还有定时器 ...
随机推荐
- android jni java类型与c语言类型互换
1.java String转换 C str char* Jstring2CStr(JNIEnv* env, jstring jstr) { char* rtn = NULL; jclass clsst ...
- RXSwift01
//创建 Observable 序列 func createObservable(){ /* let observable = Observable<Int>.just(5) let ob ...
- node-sass安装失败
1. 直接安装报错(版本根据自己需求来) npm i node-sass@ -D 报错不能下载 win32-x64-64_binding.node Downloading binary from ht ...
- forEach方法如何跳出循环
1.for方法跳出循环 function getItemById(arr, id) { var item = null; for (var i = 0; i < arr.length; i++) ...
- HDU5950【矩阵快速幂】
主要还是i^4化成一个(i+1)^4没遇到过,还是很基础的一题矩阵快速幂: #include <bits/stdc++.h> using namespace std; typedef lo ...
- Unity2d 骨骼动画1:介绍
http://bbs.9ria.com/thread-401613-1-1.html by Orlando Pereira and PedroPereira3 days ago2 Comments 在 ...
- 我不知道的C#—字符串池机制
字符串具有值类型的特点对字符串,对同一个字符串大量修改或者对多个引用赋值同一个字符串对象时会产生大量的临时字符串对象,影响性能,但是CLR为我们做了一些工作来消除这些弊端. 对同一个字符串大 ...
- perl C/C++ 扩展(五)
perl 的C++扩展,返回值为自定义类型. 在 perl C/C++扩展(三) 中,我已经介绍了,如何让perl 认识 c++的类,但是前面的介绍中,包括我参考的博客http://chunyemen ...
- StringUitl工具类中的一种写法
typeHandlersPackageArray = StringUtils.tokenizeToStringArray(this.typeAliasesPackage, ",; \t\n& ...
- CSS中em,px区别(转)
这里向大家描述一下CSS中px和em的特点和区别,px像素(Pixel),相对长度单位,像素px是相对于显示器屏幕分辨率而言的,而em是相对长度单位,相对于当前对象内文本的字体尺寸,相信本文介绍一定会 ...