动画在UI交互中是一种加强用户体验的利器,如今看到险些每一个移动App都会使用到各种动画结果。
在IOS开发中实现动画结果通常有三种方式。
- 1、基于UIView,为了方便实现简单的动画封装的UIView Animation。
- 2、基于CALayer的Core Animation框架,这是动画的底子框架。
- 3、在游戏开发中常常用到的基于物理模拟的动画框架UIKit Dynamics。【未涉及,暂不解说】
先放置了一个View测试#define Size(x) ((x)*[[UIScreen mainScreen] bounds].size.width/375.f)#define kScreenHeight [[UIScreen mainScreen] bounds].size.height#define kScreenWidth [[UIScreen mainScreen] bounds].size.width@property (nonatomic, strong) UIView *greenView;-(void)initCusView{ self.greenView = [[UIView alloc]initWithFrame:CGRectMake(0, Size(0), Size(100), Size(100))]; self.greenView.backgroundColor = UIColor.greenColor; [self.view addSubview:self.greenView];}UIView Animation
UIView Animation 参数阐明:duration : 动画履历时长delay : 延迟时间,在该延迟时间后才实举措画options : 体系提供了很多动画实验的方式,好比以下几个enum { //这部分是底子属性的设置 UIViewAnimationOptionLayoutSubviews = 1 << 0,//设置 子视图随父视图展示动画 UIViewAnimationOptionAllowUserInteraction = 1 << 1,//答应在动画实验时用户与其举行交互 UIViewAnimationOptionBeginFromCurrentState = 1 << 2,//答应在动画实验时实验新的动画 UIViewAnimationOptionRepeat = 1 << 3,//设置动画循环实验 UIViewAnimationOptionAutoreverse = 1 << 4,//设置动画反向实验,必须和重复实验一起使用 UIViewAnimationOptionOverrideInheritedDuration = 1 << 5,//欺压动画使用内层动画的时间值 UIViewAnimationOptionOverrideInheritedCurve = 1 << 6,//欺压动画使用内层动画曲线值 UIViewAnimationOptionAllowAnimatedContent = 1 << 7,//设置动画视图实时革新 UIViewAnimationOptionShowHideTransitionViews = 1 << 8,//设置视图切换时隐蔽,而不是移除 UIViewAnimationOptionOverrideInheritedOptions = 1 << 9,// //这部分属性设置动画播放的线性结果 UIViewAnimationOptionCurveEaseInOut = 0 << 16,//淡入淡出 首末减速 UIViewAnimationOptionCurveEaseIn = 1 << 16,//淡入 初始减速 UIViewAnimationOptionCurveEaseOut = 2 << 16,//淡出 末了减速 UIViewAnimationOptionCurveLinear = 3 << 16,//线性 匀速实验 //这部分设置UIView切换结果(转场动画使用) UIViewAnimationOptionTransitionNone = 0 << 20, UIViewAnimationOptionTransitionFlipFromLeft = 1 << 20,//从左边切入 UIViewAnimationOptionTransitionFlipFromRight = 2 << 20,//从右边切入 UIViewAnimationOptionTransitionCurlUp = 3 << 20,//从上面立体进入 UIViewAnimationOptionTransitionCurlDown = 4 << 20,//从下面立体进入 UIViewAnimationOptionTransitionCrossDissolve = 5 << 20,//溶解结果 UIViewAnimationOptionTransitionFlipFromTop = 6 << 20,//从上面切入 UIViewAnimationOptionTransitionFlipFromBottom = 7 << 20,//从下面切入 };animation : UIView动画竣事时的状态 ( 好比 : UIView移动到另一点,酿成某一种颜色,放大(缩小)后的比例,变革到某一透明度,视图旋转到某一角度)completion : 动画竣事时的回调(这里可以处置惩罚一些事故)usingSpringWithDamping : 阻尼(弹性系数)initialSpringVelocity : 初始速率///底子动画,竣事无回调[UIView animateWithDuration:1 animations:^{ }];///底子动画,竣事带回调[UIView animateWithDuration:1 animations:^{ } completion:^(BOOL finished) {}];///进阶动画--动员画实验的方式,竣事带回调[UIView animateWithDuration:1 delay:1 options:UIViewAnimationOptionAutoreverse|UIViewAnimationOptionRepeat animations:^{ } completion:^(BOOL finished) {}];///进阶动画--可设置弹跳结果,竣事带回调 动员画实验的方式[UIView animateWithDuration:1 delay:1 usingSpringWithDamping:0.11 initialSpringVelocity:1 options:UIViewAnimationOptionAutoreverse animations:^{ } completion:^(BOOL finished) { }];可以用来做什么呢:
设置UIView的属性:比方
frame
bounds
center
transform
alpha
backgroundColor
contentStretch
看一下实例:
self.greenView = [[UIView alloc]initWithFrame:CGRectMake(Size(30), Size(100), Size(100), Size(100))]; self.greenView.backgroundColor = UIColor.greenColor; [self.view addSubview:self.greenView];///开始动画-(void)startAnimation{ [UIView animateWithDuration:1 animations:^{///缩放比例 self.greenView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.5, 1.5);///位置调解 CGRect rect = self.greenView.frame; rect.origin.x += Size(50); rect.origin.y += Size(50); self.greenView.frame = rect;///透明度变革 self.greenView.alpha = 0.5;///color变革 self.greenView.backgroundColor = UIColor.redColor;///圆角改变 self.greenView.layer.cornerRadius = Size(50); self.greenView.clipsToBounds = YES; }];}我们可以看到self.greenView通过UIView Animation动画将某些属性举行了改变。
如今我们适当的参加一些动画实验的方式【options】
UIViewAnimationOptionRepeat:连续重复动画内容UIViewAnimationOptionCurveEaseIn:淡入UIViewAnimationOptionCurveEaseOut:淡出UIViewAnimationOptionCurveEaseInOut:淡入淡出UIViewAnimationOptionCurveLinear:匀速运动[UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{ CGRect rect = self.greenView.frame; rect.origin.x += Size(275); self.greenView.frame = rect; } completion:^(BOOL finished) {}];
在开发中可以添加特定的options满意不同的动画须要。
弹簧结果:
[UIView animateWithDuration:3 delay:0 usingSpringWithDamping:0.1 initialSpringVelocity:0 options:UIViewAnimationOptionCurveLinear animations:^{ CGRect rect = self.greenView.frame; rect.origin.x += Size(275); self.greenView.frame = rect; } completion:^(BOOL finished) { }];CABasicAnimation
CABasicAnimation 为layer属性提供了底子的帧动画本领,创建一个CABasicAnimation的实例,使用继承自CAPropertyAnimation的animationWithKeyPath:方法,来指定要添加动画的layer属性的keypath
CABasicAnimation常用的有如下几个属性://动画改变属性@property(nullable, copy) NSString *keyPath;// 指定实举措画layer的起始值@property(nullable, strong) id fromValue;// 指定竣事动画layer的竣事值@property(nullable, strong) id toValue;// 指定实举措画的时间的相对值@property(nullable, strong) id byValue;CABasicAnimation 干系常用属性/* 底子动画开始时间 CACurrentMediaTime() + 秒数 默认为0.0 这个属性在组动画中很有效 它根据父动画组的连续时间,指定了开始播放动画的时间* /@property CFTimeInterval beginTime;/* 底子动画的重复次数 默认为0.0*/@property float repeatCount;/*画应该被重复多久。动画会不绝重复,直到设定的时间流逝完。它不应该和 repeatCount 一起使用*/@property CFTimeInterval repeatDuration;/* 底子动画的时间隔断 默认为0.25*/@property CFTimeInterval duration;/* 设置为YES的时间,当动画时间隔断过了后,动画就会移除*/@property(getter=isRemovedOnCompletion) BOOL removedOnCompletion;/* 当动画时间隔断后,指定动画对象的体现。* 当地时间大概在时间隔断后大概是元素从当前体现层移除后被压缩 * 合法的值有kCAFillModeForwards、kCAFillModeBackwards、kCAFillModeBoth kCAFillModeRemoved*/@property(copy) NSString *fillMode;//设定动画的速率变革 默认:nil 使用写法:[CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut];@property(nullable, strong) CAMediaTimingFunction *timingFunction;//动画竣事时实验逆动画@property BOOL autoreverses;CABasicAnimation的写法。
移动动画
让一个view向左平移,在x方向上从屏幕x中心线型移动到左边消散,耗时1.5秒的动画
第一种方法:// 创建动画 使用动画改变属性 position.x CABasicAnimation *positionAnima = [CABasicAnimation animationWithKeyPath"position.x"]; // 指定底子动画的时间隔断,以秒为单元默认值是 0.25positionAnima.duration = 1.5;//改变前的属性positionAnima.fromValue = @((kScreenWidth-Size(100))/2);//改变后的属性positionAnima.toValue = @(-self.greenView.frame.size.width / 2);//生存最新状态positionAnima.fillMode = kCAFillModeForwards;//动画组件不被移除positionAnima.removedOnCompletion = NO;[self.greenView.layer addAnimation:positionAnima forKey"position.x"];第二种方法:// 创建动画CABasicAnimation *positionAnima = [CABasicAnimation animation];// 动画改变属性positionAnima.keyPath = @"position";positionAnima.duration = 1.5;// 改变后的属性positionAnima.toValue = [NSValue valueWithCGPoint:CGPointMake(-Size(50), Size(100+50))];// 动画组件不被移除positionAnima.removedOnCompletion = NO; // 生存最新状态positionAnima.fillMode = kCAFillModeForwards;[self.greenView.layer addAnimation:positionAnima forKey"position"]; 区别:设置的keypath不同第一种方法指定了左移,第二种方法可以是上下左右移动,fromValue、toValue须要根据keypath属性改变旋转动画
5s完成旋转一周的顺时针旋转的view 并连续旋转CABasicAnimation * rotationAnimation = [CABasicAnimation animationWithKeyPath"transform.rotation.z"];rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 ];rotationAnimation.duration = 5;rotationAnimation.cumulative = YES;rotationAnimation.repeatCount = HUGE_VAL;rotationAnimation.removedOnCompletion = NO;[self.greenView.layer addAnimation:rotationAnimation forKey"rotationAnimation"];缩放动画
/* 放大缩小 */ // 设定为缩放CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath"transform.scale"];// 动画选项设定animation.duration = 2.5; // 动画连续时间animation.repeatCount = 1; // 重复次数animation.autoreverses = YES; // 动画竣事时实验逆动画// 缩放倍数animation.fromValue = [NSNumber numberWithFloat:1.0]; // 开始时的倍率animation.toValue = [NSNumber numberWithFloat:2.0]; // 竣事时的倍率// 添加动画[self.greenView.layer addAnimation:animation forKey"scale-layer"];KeyPath的改变更画的结果就不一样,开发中改变KeyPath的属性可以实现大多数我们须要的动画实验的结果
animationWithKeyPath值范例:
position = 路径(一样寻常用CAKeyframeAnimation)transform.rotation = 旋转transform.rotation.x = x旋转transform.rotation.y = y旋转transform.rotation.z = z旋转(顺逆时针)transform.translation = 平移transform.translation.x = x平移transform.translation.y = y平移transform.scale = 比例转换transform.scale.x = x的比例转换transform.scale.y = y的比例转换transform.scale.y = y的比例转换transform.rotation.z = 平面圆的转换opacity = 透明度marginzPositionbackgroundColor = 配景颜色cornerRadius = 圆角borderWidthboundscontentscontentsRectcornerRadiusframe 坐标hidden 隐蔽maskmasksToBoundsshadowColorshadowOffsetshadowOpacityshadowRadius各人可以实验使用不同的keypath看看动画结果用CABasicAnimation实举措画,在动画竣事后会回归动画开始前的状态。想要办理的话,必须设置“removedOnCompletion”和“fillMode”这两个属性。
// 动画终了后不返回初始状态animation.removedOnCompletion = NO;animation.fillMode = kCAFillModeForwards;但是
由于在开发过程中光是CABasicAnimation的fromValue、toValue出发点和终点设置是无法满意我们盼望在动画中途举行更多的变革的需求,以是我们须要熟悉一下CAKeyframeAnimation
CAKeyframeAnimation[关键帧动画]
从上面的继承图我们看出CAKeyframeAnimation 比CABasicAnimation多了更多的可设置属性
/* 提供关键帧数据的数组,数组中的每一个值都对应一个关键帧。根据动画范例(keyPath)的不同 ,值的范例不同*/@property(nullable, copy) NSArray *values;/*基于点的属性的路径,即动画属性范例为CGPoint。如: position、anchorPoint、transform.translation等如果为此属性指定非空值,则会忽略values属性*/@property(nullable) CGPathRef path;/* keyTimes的值与values中的值逐一对应指定关键帧在动画中的时间点,取值范围为[0,1]。当keyTimes没有设置的时间,各个关键帧的时间是中分的*/@property(nullable, copy) NSArray*keyTimes;/*指定每个关键帧之间的动画缓冲结果,timingFunctions.count = keyTimes.count-1*/@property(nullable, copy) NSArray*timingFunctions;/*关键帧间插值盘算模式*/@property(copy) NSString *calculationMode;/*针对cubic 盘算模式的动画,这些属性提供对插值方案的控制。每个*关键帧都可以具有与之干系的张力、连续性和毛病值,这些值的范围在[-1,1]内(这界说了Kochanek-*Bartels样条,见http://en.wikipedia.org/wiki/Kochanek-Bartels_spline)。*tensionValues控制曲线的“紧密度”(正值更紧,负值更圆)。*continuityValues控制段的毗连方式(正值表现锐角,负值表现倒角)。*biasValues界说曲线发生的位置(正值在控制点之前移动曲线,负值在控制点之后移动它)。*每个数组中的第一个值界说第一个控制点的切线的举动,第二个值控*制第二个点的切线,依此类推。任何未指定的值都默认为零 *(如果未指定,则给出Catmull-Rom样条曲线)。 */@property(nullable, copy) NSArray*tensionValues;@property(nullable, copy) NSArray*continuityValues;@property(nullable, copy) NSArray *biasValues;/*界说沿路径动画的对象是否旋转以匹配路径切线*/@property(nullable, copy) NSString *rotationMode;关键帧动画其实通过一组动画范例的值(大概一个指定的路径)和这些值对应的时间节点以及各时间节点的过渡方式来控制显示的动画。关键帧动画可以通过path属性和values属性来设置动画的关键帧。
通过path设置动画
绕线一周动画CGMutablePathRef path = CGPathCreateMutable();//第一个关键帧 -100,-100CGPathMoveToPoint(path, NULL, 0, 0);//第二个关键帧 100,-100CGPathAddLineToPoint(path, NULL, 100, 0);//第三个关键帧 100,100 CGPathAddLineToPoint(path, NULL, 100, 100);//第四个关键帧 -100,100CGPathAddLineToPoint(path, NULL, 0, 100);//第五个关键帧 -100,-100CGPathAddLineToPoint(path, NULL, 0, 0); CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];animation.keyPath = @"transform.translation";animation.path = path;animation.duration = 4;animation.keyTimes = @[@(0),@(0.1),@(0.5),@(0.75),@(1)];animation.timingFunctions = @[[CAMediaTimingFunction functionWithControlPoints:1 :0.5 :0.5 :0.5], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]]; //动画竣事后保持动画末了的状态,两个属性需配合使用 animation.removedOnCompletion = NO;animation.fillMode = kCAFillModeForwards; CGPathRelease(path);[self.greenView.layer addAnimation:animation forKey""];通过values设置动画
/// 放大缩小放大缩小【隐蔽】CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath"transform.scale"];animation.duration = 2.0;// 动画时间animation.removedOnCompletion = NO;animation.values = @[@1,@1.2,@1,@1.2,@0];//动画竣事后保持动画末了的状态,两个属性需配合使用animation.removedOnCompletion = NO;animation.fillMode = kCAFillModeForwards;[self.greenView.layer addAnimation:animation forKey:nil];CAAnimationGroup[动画组]
可以生存一组动画CAKeyframeAnimation、CABasicAnimation对象,将CAAnimationGroup对象参加图层后,组中全部动画对象可以同时并发运行。
购物车动画
/* 动画1(在XY轴方向移动) */CABasicAnimation *animation1 = [CABasicAnimation animationWithKeyPath"transform.translation"];// 终点设定animation1.toValue = [NSValue valueWithCGPoint:CGPointMake(kScreenWidth-Size(50), kScreenHeight-Size(50))]; // 終点/* 动画2(绕Z轴中心旋转) */CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];// 设定旋转角度animation2.fromValue = [NSNumber numberWithFloat:0.0]; // 开始时的角度animation2.toValue = [NSNumber numberWithFloat:4 * M_PI]; // 竣事时的角度 /* 动画组 */ CAAnimationGroup *group = [CAAnimationGroup animation];// 动画选项设定group.duration = 3.0;group.repeatCount = 1;// 添加动画group.animations = [NSArray arrayWithObjects:animation1, animation2, nil];[self.greenView.layer addAnimation:group forKey:@"move-rotate-layer"];留意:默认环境下,一组动画对象是同时运行的,也可以通过设置单个动画对象的beginTime属性来更改动画的开始时间,单个动画的实验结果可以与动画组实验结果属性分开设定,根据须要调解改变。 |