转场动画,可以很炫酷的转场动画

登入页分解、落成

  • 点击了GET开关,logo图和logo文字上移

    图片 1logo移动.gif

    思路:移动属于相比较轻便的操作,但这么些运动作效果果有所弹簧效果,所以能够接纳大旨动画中的关键帧动画CAKeyframeAnimation,也许pop动画来实现,这里自身用了pop,后边登陆退步按键左右颤巍巍的动画,小编用了CAKeyframeAnimation。代码:

//图片移动动画POPSpringAnimation *anim4 = [POPSpringAnimation animationWithPropertyNamed:kPOPViewFrame];//kPOPViewFrame表示改变的值是frame//动画开始的值(.yy_x是我写的分类的语法,等同于.frame.origin.x,其它同理)anim4.fromValue = [NSValue valueWithCGRect:CGRectMake(self.LoginImage.yy_x, self.LoginImage.yy_y, self.LoginImage.yy_width, self.LoginImage.yy_height)];//动画结束时的值anim4.toValue = [NSValue valueWithCGRect:CGRectMake(self.LoginImage.yy_x, self.LoginImage.yy_y-75, self.LoginImage.yy_width, self.LoginImage.yy_height)];//开始的时间anim4.beginTime = CACurrentMediaTime() 0.2;//弹性系数anim4.springBounciness = YYSpringBounciness;//YYSpringBounciness是我定义的静态变量,值是16.0//速度anim4.springSpeed = YYSpringSpeed;//YYSpringSpeed是我定义的静态变量,值是6.0//加到控件上执行[self.LoginImage pop_addAnimation:anim4 forKey:nil];//文字移动动画POPSpringAnimation *anim5 = [POPSpringAnimation animationWithPropertyNamed:kPOPViewFrame];anim5.fromValue = [NSValue valueWithCGRect:CGRectMake(self.LoginWord.yy_x, self.LoginWord.yy_y, self.LoginWord.yy_width, self.LoginWord.yy_height)];anim5.toValue = [NSValue valueWithCGRect:CGRectMake(self.LoginWord.yy_x, self.LoginWord.yy_y-75, self.LoginWord.yy_width, self.LoginWord.yy_height)];anim5.beginTime = CACurrentMediaTime() 0.2;anim5.springBounciness = YYSpringBounciness;anim5.springSpeed = YYSpringSpeed;[self.LoginWord pop_addAnimation:anim5 forKey:nil];
  • 点击get按键出现输入框

    图片 2get开关形变移动.gif

    1、get开关的转移思路:get按钮分别开展了变宽、变宽的同有时间圆角变小,然后变高,然后向上移动,整个过程颜色由开头颜色变白。由于这是N个动画,有同期实施的,有接着上一步实践的,所以本人选择大旨动画CABasicAnimation,更便于调整每种动画的实践时间、起始时间,轻巧接通得流畅。代码:

//get背景颜色CABasicAnimation *changeColor1 = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];changeColor1.fromValue = (__bridge id)ButtonColor.CGColor;changeColor1.toValue = (__bridge id)[UIColor whiteColor].CGColor;changeColor1.duration = 0.8f;changeColor1.beginTime = CACurrentMediaTime();//以下两个参数,是为了动画完成后,控件的样子不回到动画前的样子//因为上文中提到过,核心动画是给layer做动画,控件本身的属性不会变changeColor1.fillMode = kCAFillModeForwards;changeColor1.removedOnCompletion = false;[animView.layer addAnimation:changeColor1 forKey:changeColor1.keyPath];//get按钮变宽CABasicAnimation *anim1 = [CABasicAnimation animationWithKeyPath:@"bounds.size.width"];anim1.fromValue = @(CGRectGetWidth(animView.bounds));anim1.toValue = @(YYScreenW*0.8);anim1.duration = 0.1;anim1.beginTime = CACurrentMediaTime();anim1.fillMode = kCAFillModeForwards;anim1.removedOnCompletion = false;[animView.layer addAnimation:anim1 forKey:anim1.keyPath];//get按钮变高CABasicAnimation *anim2 = [CABasicAnimation animationWithKeyPath:@"bounds.size.height"];anim2.fromValue = @(CGRectGetHeight(animView.bounds));anim2.toValue = @(YYScreenH*0.3);anim2.duration = 0.1;anim2.beginTime = CACurrentMediaTime() 0.1;anim2.fillMode = kCAFillModeForwards;anim2.removedOnCompletion = false;[animView.layer addAnimation:anim2 forKey:anim2.keyPath];//get按钮移动动画//这里的移动跟logo的移动是同步的,所以用popPOPSpringAnimation *anim3 = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];anim3.fromValue = [NSValue valueWithCGRect:CGRectMake(animView.yy_centerX, animView.yy_centerY, animView.yy_width, animView.yy_height)];anim3.toValue = [NSValue valueWithCGRect:CGRectMake(animView.yy_centerX, animView.yy_centerY-75, animView.yy_width, animView.yy_height)];anim3.beginTime = CACurrentMediaTime() 0.2;anim3.springBounciness = YYSpringBounciness;anim3.springSpeed = YYSpringSpeed;[animView pop_addAnimation:anim3 forKey:nil];

2、输入框出现、LOGIN开关出现思路:输入框是发光度的改动,LOGIN按键是大大小小的改换。代码:

//账号密码输入框出现self.userTextField.alpha = 0.0;self.passwordTextField.alpha = 0.0;[UIView animateWithDuration:0.4 delay:0.2 options:UIViewAnimationOptionCurveEaseInOut animations:^{ self.userTextField.alpha = 1.0; self.passwordTextField.alpha = 1.0;} completion:^(BOOL finished) { }];//login按钮出现动画self.LoginButton.yy_centerX = YYScreenW*0.5;self.LoginButton.yy_centerY = YYScreenH*0.7 44 (YYScreenH*0.3-44)*0.5-75;CABasicAnimation *animLoginBtn = [CABasicAnimation animationWithKeyPath:@"bounds.size"];animLoginBtn.fromValue = [NSValue valueWithCGSize:CGSizeMake];animLoginBtn.toValue = [NSValue valueWithCGSize:CGSizeMake(YYScreenW*0.5, 44)];animLoginBtn.duration = 0.4;animLoginBtn.beginTime = CACurrentMediaTime() 0.2;animLoginBtn.fillMode = kCAFillModeForwards;animLoginBtn.removedOnCompletion = false;animLoginBtn.delegate = self;//在代理方法里,让按钮真正的宽高改变,而不仅仅是它的layer,否则看得到点不到[self.LoginButton.layer addAnimation:animLoginBtn forKey:animLoginBtn.keyPath];/** 动画执行结束回调 */- animationDidStop:(CAAnimation *)anim finished:flag{ if ([((CABasicAnimation *)anim).keyPath isEqualToString:@"bounds.size"]) { self.LoginButton.bounds = CGRectMake(YYScreenW*0.5, YYScreenH*0.7 44 (YYScreenH*0.3-44)*0.5-75, YYScreenW*0.5, 44); }}
  • 点击LOGIN,按键转圈

    图片 3按键转圈.gif

    思路:点击了LOGIN,按键先从宽变圆,然后给按键增加一条半圆的反动圆弧线,然后让这么些开关开始转动。代码:

//执行登录按钮转圈动画的view//为了不影响按钮本身的效果,这里新建一个空间做转圈动画self.LoginAnimView = [[UIView alloc] initWithFrame:self.LoginButton.frame];self.LoginAnimView.layer.cornerRadius = 10;self.LoginAnimView.layer.masksToBounds = YES;self.LoginAnimView.frame = self.LoginButton.frame;self.LoginAnimView.backgroundColor = self.LoginButton.backgroundColor;[self.view addSubview:self.LoginAnimView];self.LoginButton.hidden = YES;//把view从宽的样子变圆CGPoint centerPoint = self.LoginAnimView.center;CGFloat radius = MIN(self.LoginButton.frame.size.width, self.LoginButton.frame.size.height);[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ self.LoginAnimView.frame = CGRectMake(0, 0, radius, radius); self.LoginAnimView.center = centerPoint; self.LoginAnimView.layer.cornerRadius = radius/2; self.LoginAnimView.layer.masksToBounds = YES; }completion:^(BOOL finished) { //给圆加一条不封闭的白色曲线 UIBezierPath* path = [[UIBezierPath alloc] init]; [path addArcWithCenter:CGPointMake(radius/2, radius/2) radius:(radius/2 - 5) startAngle:0 endAngle:M_PI_2 * 2 clockwise:YES]; self.shapeLayer = [[CAShapeLayer alloc] init]; self.shapeLayer.lineWidth = 1.5; self.shapeLayer.strokeColor = [UIColor whiteColor].CGColor; self.shapeLayer.fillColor = self.LoginButton.backgroundColor.CGColor; self.shapeLayer.frame = CGRectMake(0, 0, radius, radius); self.shapeLayer.path = path.CGPath; [self.LoginAnimView.layer addSublayer:self.shapeLayer]; //让圆转圈,实现"加载中"的效果 CABasicAnimation* baseAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"]; baseAnimation.duration = 0.4; baseAnimation.fromValue = @; baseAnimation.toValue = @; baseAnimation.repeatCount = MAXFLOAT; [self.LoginAnimView.layer addAnimation:baseAnimation forKey:nil];}];
  • 签到失败按键抖动

    图片 4登入退步按键动画.gif

    思路:那些成效跟pop动画移动后震荡的成效很接近,这里笔者选取用关键帧动画CAKeyframeAnimation做,它与CABasicAnimation略有差异,CABasicAnimation是从二个值到另三个值,CAKeyframeAnimation是值变化的数组。代码:

//给按钮添加左右摆动的效果CAKeyframeAnimation *keyFrame = [CAKeyframeAnimation animationWithKeyPath:@"position"];CGPoint point = self.LoginAnimView.layer.position;//这个参数就是值变化的数组keyFrame.values = @[[NSValue valueWithCGPoint:CGPointMake(point.x, point.y)], [NSValue valueWithCGPoint:CGPointMake(point.x - 10, point.y)], [NSValue valueWithCGPoint:CGPointMake(point.x   10, point.y)], [NSValue valueWithCGPoint:CGPointMake(point.x - 10, point.y)], [NSValue valueWithCGPoint:CGPointMake(point.x   10, point.y)], [NSValue valueWithCGPoint:CGPointMake(point.x - 10, point.y)], [NSValue valueWithCGPoint:CGPointMake(point.x   10, point.y)], [NSValue valueWithCGPoint:point]];//timingFunction意思是动画执行的效果(这个属性玩HTML CSS的童鞋应该很熟悉吧)//kCAMediaTimingFunctionEaseInEaseOut表示淡入淡出keyFrame.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];keyFrame.duration = 0.5f;[self.LoginButton.layer addAnimation:keyFrame forKey:keyFrame.keyPath];
2、 实现UIViewControllerTransitioningDelegate情商酌程

垄断器A服从UIViewControllerTransitioningDelegate左券,并促成如下多个代理方法。第贰个代理方法是决定器A步向调整器B的时候调用,第三个代理方法是决定器B回到调控器A时调用。ZWAnimationPresentProxyZWAnimationDismissProxy是自定义类,关于那七个类请看第三步和第四手续。

//控制器A----B的转场动画//方法的返回值表示当View呈现的时候要通过那个对象来执行动画 - (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source{ //在此方法中要返回一个对象,该对象要遵守<UIViewControllerAnimatedTransitioning>协议,在该对象对应的类中实现代理方法 ZWAnimationPresentProxy *presentProxy = [[ZWAnimationPresentProxy alloc]init]; return presentProxy;}

////控制器B----A的转场动画////控制器在dismiss的时候通过那个对象来执行转场动画 - (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed{ //在此方法中要返回一个对象,该对象要遵守<UIViewControllerAnimatedTransitioning>协议,在该对象对应的类中实现代理方法 ZWAnimationDismissProxy *dismissProxy = [[ZWAnimationDismissProxy alloc]init]; return dismissProxy;}
 //按钮的点击方法
    func actionDidClickAddButton(sender:UIButton)
    {
        sender.enabled = false
        let centerPoint = contentView.convertPoint(imageView.center, toView: XHRKeyWindow)
        delegate?.collectionViewCellDidClickAddButton(imageView.image,centerPoint: centerPoint,button:sender)
    }

需求

一般来说图。DEMO下载地址:

图片 5动画片效果

评释:为了更方面包车型地铁表达黑色背景的调整器称为A调节器,石青背景的调节器称为B调整器。

德姆o下载链接:

   //动画结束后调用的代理方法,将动画的imageView移除,将来还有刷新购物车数据之类的事情可以在这个方法里面做
   override func animationDidStop(anim: CAAnimation, finished flag: Bool) {
//移除动画imageView
       self.animationView?.removeFromSuperview()
//发出添加完成的通知(伪代码)  
NSNotificationCenter.defaultCenter().postNotificationName(XHRSucceedAddToShoppingMartNotification, object: "商品ID")
   }

转场动画分解、完结

图片 6转场动图.gif图片 7转场图.png

思路:如上航海用体育场所AB调整器原来的面目是如此,转场动画须求做到一下操作:1、LOGO图逐步消退;2、LOGO文字渐渐变小、上移至B中底部文字的职位;3、A调节器的登入框消失、A调节器背景颜色变白;4、转圈控件经过弧线运动到右下角,金黄加号渐渐产生5、B调整器背景图上移的动画片。下边深入分析下第4步和第2步的做法。

  • 圆形的弧线位移、加号的现身

    图片 8圆形的弧线位移、加号的面世.gif

    思路:先用设定一条曲线,然后让圆沿着曲线移动,最后把加号体现出来。代码:

//设定曲线CGMutablePathRef path = CGPathCreateMutable();//开始的点CGPathMoveToPoint(path, NULL, (circularAnimView.yy_x circularAnimView.yy_width*0.5), (circularAnimView.yy_y circularAnimView.yy_height*0.5));//设置结束的点和拉力点,第三个参数是拉力点CGPathAddQuadCurveToPoint(path, NULL, YYScreenW*0.9, circularAnimView.yy_y circularAnimView.yy_height, (originalX circularAnimView.yy_width*0.5), (originalY circularAnimView.yy_height*0.5));CAKeyframeAnimation *animate = [CAKeyframeAnimation animationWithKeyPath:@"position"];animate.delegate = self;//在动画结束的代理方法中让加号出现animate.duration = 0.4;animate.beginTime = CACurrentMediaTime() 0.15;animate.fillMode = kCAFillModeForwards;animate.repeatCount = 0;animate.path = path;//移动路径animate.removedOnCompletion = NO;CGPathRelease;[circularAnimView.layer addAnimation:animate forKey:@"circleMoveAnimation"];

生成曲线的法规:设置起首的点、甘休的点、拉力点,首先会从开端点指停止点变成一条直线,然后向拉力点盘曲,就恍如,拉力点会“伸出一头手”,把线拉弯。

图片 9曲线原理暗中表示.png加号渐渐绘制的功用:另一篇小说里聊起了这种线稳步绘制的动画片,可以参照一下:

  • logo文字的压缩、移动

    图片 10logo文字的形变和移动.gif

    思路:那是三个UILabel,它的形变就无法靠改换frame达成了,因为只要您降低它的肥瘦,当宽度远远不够装内容时,内容会展现不全,呈现不下的会用...代替。所以减少UILabel要求靠特地的形变属性。至于移动就好说了,只须要算准地方。代码:

CGFloat proportion = toVC.navWord.yy_width / fromVC.LoginWord.yy_width;CABasicAnimation * LoginWordScale = [CABasicAnimation animationWithKeyPath:@"transform.scale"];LoginWordScale.fromValue = [NSNumber numberWithFloat:1.0];LoginWordScale.toValue = [NSNumber numberWithFloat:proportion];LoginWordScale.duration = 0.4;LoginWordScale.beginTime = CACurrentMediaTime() 0.15;LoginWordScale.removedOnCompletion = NO;LoginWordScale.fillMode = kCAFillModeForwards;[fromVC.LoginWord.layer addAnimation:LoginWordScale forKey:LoginWordScale.keyPath];CGPoint newPosition = [toVC.view convertPoint:toVC.navWord.center fromView:toVC.navView];[UIView animateWithDuration:0.4 delay:0.15 options:UIViewAnimationOptionCurveEaseInOut animations:^{ fromVC.LoginWord.yy_centerX = newPosition.x; fromVC.LoginWord.yy_centerY = newPosition.y;} completion:^(BOOL finished) { }];

四、自定义转场动画

打探了地点的连带东西之后,接下去便足以真正起首攻读转场动画了,先总的说一下跌实转场动画要做怎么样盘算。

2.cell的说明
由于开关是在cell上,可是购物车是在tabBar上,由此假诺一贯在cell中贯彻动画想获得tabBar上控件坐标是相比较费心的事务,小编这里是运用了代办方法,把点击事件抛给调节器,代码如下:

急需剖判

  • 解析方法下载这几个gif动图,用mac暗许的展开药格局张开那几个gif图,效果如下

    图片 1101.png

    鼠标选中群青箭头所指的岗位,然后按住键盘方向键下键,图片会以减缓的可控的速度播放,便于剖析动画的重组。

  • 小tips:macos系统想符合规律浏览叁个gif动图,能够鼠标单击图片后按空格,也足以挑选取浏览器展开,gif图会以不荒谬进程播放。

4、ZWAnimationDismissProxy类的兑现。

若是能够讲第3步骤中的达成给完全看懂,这一步基本是一模一样。直接上代码。再次来到转场动画的持续时间。

//返回转场动画的持续时间- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext{ return 0.5;}

其一法子中收获到B调整器的蓝灰View,如若偏移的角度丰富大就能够调用B调控器中的[self dismissViewControllerAnimated:YES completion:nil];方法,进而调用那么些代理方法中落到实处的代码。如若偏移的角度不充分就不会调用[self dismissViewControllerAnimated:YES completion:nil];方法以及这些代理方法中完毕的代码。

//编写具体的转场动画代码[消失的时候]//说明:只要实现了这个代理方法,必须自己来编写具体的转场代码,系统的转场方式消失。如果不实现此方法,界面无法跳转- animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext{ //1、获取这个转场动画的framView UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey]; //2、执行动画 //动画时间直接设置为转场动画的时间,系统默认时间是0.25s [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{ //判断view的旋转角度 if (fromView.transform.b > 0) { fromView.transform = CGAffineTransformMakeRotation; }else{ fromView.transform = CGAffineTransformMakeRotation; } } completion:^(BOOL finished) { //3、转场动画结束后必须调用[transitionContext completeTransition:YES];方法。 //如果不调用该方法,dismiss的界面将无法监听任何事件,界面直接不能进行交互 [transitionContext completeTransition:YES]; }];}
  • 率先剖断需求做动画的image存在与否
  • 应用给定的image创造四个和原岗位一样的UIImageView加多到窗口上,这里传出去的大旨点是因而坐标转化过的主窗口的基本点坐标

转场动画的原理和达成形式

上文提起,从A跳向B,须求壹其中等载体来做动画,那么怎么获得那几个载体呢?供给采纳转场代理transitioningDelegate。

  • 具体做法、步骤:1、从A调节器跳到B调节器,写跳转的代码时候,赋值代理
 YYFirstViewController *vc = [[YYFirstViewController alloc] init]; vc.transitioningDelegate = self;//也就是这里 [self presentViewController:vc animated:YES completion:nil];

2、A调控器遵守代理,实现代理方法

//遵守代理@interface YYLoginViewController () <UIViewControllerTransitioningDelegate>#pragma mark UIViewControllerTransitioningDelegate//这个是B回到A时执行的方法- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed{ //暂时别纠结YYLoginTranslation是什么,看下文 YYLoginTranslation *loginTranslation = [[YYLoginTranslation alloc] init]; return loginTranslation;}//这个是A跳到B时执行的方法- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source{ YYLoginTranslation *loginTranslation = [[YYLoginTranslation alloc] init]; return loginTranslation;}

3、综上说述,上述四个艺术要求回到二个遵守了<UIViewControllerAnimatedTransitioning>那么些代理的靶子,所以,以后亟待新建一个类遵从这一个代理,实现四个代理方法

//类的.h文件#import <Foundation/Foundation.h>#import <UIKit/UIKit.h>@interface YYLoginTranslation : NSObject <UIViewControllerAnimatedTransitioning>@end//类的.m文件#import "YYLoginTranslation.h"@interface YYLoginTranslation () <CAAnimationDelegate>@end@implementation YYLoginTranslation//代码方法-转场时长- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{ return 1.0;}//代理方法-转场动画的代码- animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{ //transitionContext:转场上下文 //转场过程中显示的view,所有动画控件都应该加在这上面 //这就是那个所谓的载体 UIView* containerView = [transitionContext containerView]; //在这里把要做动画效果的控件往containerView上面加 //开始开心的做动画 //最后,在动画完成的时候,记得标识转场结束 [transitionContext completeTransition:YES];}

4、以往悔过看第2步,那二个再次来到的靶子,正是大家第三步创造的类的对象。从A跳到B开头时,会先过来第2步中的"那个是A跳到B时实行的情势",依据你回来的对象,去对象中找代理方法,试行里面的代码,也正是第三步中的"代理方法-转场动画的代码"那个情势,这里代码执行甘休后,调节器跳转也就完毕了。

一、系统转场中的视图等级次序深入分析

以多个归纳的present效果来剖析下转场过中的分界面结构,调整器A的背景设为灰绿,调控器B的背景设置为铅灰,然后点击调整器A以model的款型跳转到调控器B。跳转代码如下:

 //常规的转场 ViewController2 *vc = [[ViewController2 alloc]init]; //修改转场动画效果 vc.modalTransitionStyle = UIModalPresentationPageSheet; [self presentViewController:vc animated:YES completion:nil];

图片 12系统转场视图层级分析

当模态进入后,会发现A调整器的紫蓝view消失了。总共有三层,从左到右贰回是UIWindow,UITransitionView容器视图,B调整器的浅蓝view。当中UITransitionView是多少个器皿视图,每一种调控器都有其承载,转场动画中它扮演二个相当重大的剧中人物。关于系统的转场动画,仅了然那么些就够用,接下去看下自定义转场的视图档次解析。

在那网络经济漫天掩地的时代,购物车相信我们都不生分。近日被三个敌人问起购物网络麻豆块的贯彻,恰好这段日子五个类型也会有涉嫌到购物车那么些模块,只不过当时是用OC写的,所以就分模块写了个Swift版的demo。
1.首页的布局
近些日子假诺首页的布局是采用UICollectionView的布局,自定义cell和flowLayout,每三个cell上显得的都以局地商品新闻,然后有一个加号加多按键,完毕代码很粗大略就不详述了(可看demo),效果具体如图

备注

  • POP框架的手动集成报错的标题pop框架推荐应用pods集成,要是要手动集成的话,相比较费心,由于管理这些主题素材的时光已经有一些久了,集成的麻烦点记不全了,大致就是它框架里的兼具头文件的import方式要从<>改成"",还应该有它就像是有个.cpp文件,要把后缀改成.mm,还应该有怎么着记不住了。若是要求手动集成pop框架,能够下那几个demo,里面有手动集成的pop框架,直接把方方面面文件夹拖走就能够。
  • 德姆o下载地址:

今日的指标很轻松,做叁个仿酷小编音乐播放器的转场动画。并以这些案列周密调节转场动画。先看效果图。如上面包车型的士gif图片,点击开关可以进来另外三个淡黄背景的调节器,左右滑行乌紫背景的调节器能够回来到深翠绿背景的调整器。况且滑动的时候还应该有动画效果!效果还算高大上,只是分界面有点丑。

  • 卡通分四个部分:第四个是CABasicAnimation,别的二个是CAKeyframeAnimation。CABasicAnimation是用来做旋转动画的,CAKeyframeAnimation是用来做抛物线动画的。然后把二者参预动画组就OK。每一步解释请看注释:
  • endPoint 那几个坐标是购物车的中央点坐标转化为主窗口上的坐标,具体的代码实现是在自定义UITabBarController中贯彻的,代码如下

退出登录动画

图片 13剥离登入.gif

思路:那么些功用相比较轻松,但同不时候也相比实用。达成格局就是改换七个调控器view的折射率。代码:

//transitionContext:转场上下文//转场过程中显示的view,所有动画控件都应该加在这上面UIView *containerView = [transitionContext containerView];//转场的来源控制器YYLoginViewController* toVC = (YYLoginViewController *)[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];//转场去往的控制器YYFirstViewController* fromVC = (YYFirstViewController *)[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];//做一个淡入淡出的效果toVC.view.alpha = 0;[containerView addSubview:toVC.view];[UIView animateWithDuration:1.0 animations:^{ fromVC.view.alpha = 0;} completion:^(BOOL finished) {}];[UIView animateWithDuration:0.6 delay:0.4 options:UIViewAnimationOptionCurveEaseInOut animations:^{ toVC.view.alpha = 1;} completion:^(BOOL finished) { [transitionContext completeTransition:YES];}];
5、转场动画的贯彻。

这一手续实际上就是前方的卡通效果的贯彻,具体请看 三、动画效果的达成.这一步骤的得以实现。

本领点剖析

  • 怎么着生成三个卡通让控件试行?现流行的办法根本有二种:1、基本动画2、主题动画3、三方框架——POP框架(由照片墙开荒)它们的重大差别:1、控件的岗位、大小等是或不是当真产生了改变?基本动画、pop动画,是给控件增多动画(一般也不会有用为重动画给layer增加动画的做法),全数动画达成时,控件的习性已经济体改成,而基本动画,是给控件的图层(view.layer)增多动画,看似发生了职分大小的变动,实际上控件自个儿的品质并未有改造。2、它们分别的优劣势2.1、基本动画优势:代码轻巧,代码量少劣点:成效相对单一2.2、主题动画的优势优势:作用强大、流畅性好、一连多少个卡通之间的衔接度好。流畅首倘诺因为操作layer是轻量级的,不易于爆发动画卡顿的感觉。劣点:代码量大;轻巧写错(有些参数没有定义宏,写错了都不亮堂);如有须求,还要手动在动画达成时将控件的属性同步修改了。2.3、pop动画的优势优势:比核心动画代码要不难,最大的优势在于,轻便做弹簧效果,所以广大有“Q弹”感觉的都用pop动画做劣点:要在一个动画完成时伊始另三个动画片,pop动画不专长,首要因为它的卡通施行时间由"速度"和"弹性周全"五个参数调整,不佳直观推断动画施行了多长期,而假使在pop动画完结回调的block里提交下叁个卡通,会不连贯。

  • 转场动画怎么落到实处?明明从A调节器跳往B调节器,各是各的页面,各是各的控件,怎么造成A里的控件变化造成了B的控件的服从?的确,A和B是五个独立的页面,它们跳转进度须要动画的效果时,供给别的五个人作品表现于显示器上的载体来装那么些做动画的控件,然后在动画完毕、转场截至时,把这么些载体移除掉,发布转场结束,这一年把真的的B的页面呈现出来。那就必要转场代理transitioningDelegate发挥成效了,具体做法和原理下文详述。

二、自定义转场的视图档案的次序解析

万一将跳转代码改为如下情势:

 ViewController2 *vc = [[ViewController2 alloc]init]; //自定义转场 vc.modalPresentationStyle = UIModalPresentationCustom; [self presentViewController:vc animated:YES completion:nil];

vc.modalPresentationStyle = UIModalPresentationCustom;是完结自定义转场动画必得实行的一句代码。

图片 14自定义转场的视图等级次序解析

那是能够看到分界面包车型大巴档次结构,从左到右依次为(排除中间三个小小的的视图),UIWindow,A调控器的view,UITransitionView容器视图,B调节器的view。中间蓝绿背景樱桃红边框的为容器视图,转场动画重要正是通过它完结的。同系统的转场相相比较,设置为自定义转场后,A调节的View依旧可知。之所以是可知的,因为设置为自定义转然后大家需求达成部分特殊效果,会接纳到上一分界面所表现的UI,定制特殊的转场动画效果。

cell展示图.png

1、设置自定义转场动画,裁撤系统的转场动画

设置vc.modalPresentationStyle = UIModalPresentationCustom;

ViewController2 *vc = [[ViewController2 alloc]init]; //设置自定义转场 vc.modalPresentationStyle = UIModalPresentationCustom; //注意不是modalTransitionStyle而是modalPresentationStyle,如果这里写错了,则模态到下一界面的时候,上一界面的背景不在显示 //vc.modalTransitionStyle = UIModalPresentationCustom; //设置代理自定义转场 vc.transitioningDelegate = self; [self presentViewController:vc animated:YES completion:nil];

Tips:以上是自己项目中的需要,具体的还要看各种人的供给,能够在组动画上入手脚来实现不一致的动画方式。
demo地址:https://github.com/xuhongru/ShoppingCartAnimation
作者:胥鸿儒

小结

假诺通晓了如上套路,实际付出中的转场特效也不过那样,入眼的特效动画只要在上边那么些合同格局中落成就可以。参数transitionContext表示的是转场中饱含的新闻,全体转场进度中带有的消息都足以从那当中获得。既然都能够获得到对应控件了,剩下的正是常规的装置动画效果了。这么些主意只怕十二分首要的。

- animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext;

4.最中央的部分动画片部分

3、ZWAnimationPresentProxy类的贯彻。

ZWAnimationPresentProxyZWAnimationDismissProxy那四个类都以继续与NSObject,且都要遵守<UIViewControllerAnimatedTransitioning>左券,在那一个类中倘诺达成八个公约章程就能够。设置转场动画的持续时间。

//返回转场动画的持续时间- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext{ return 0.5;}

这么些主意中的代码才是转场动画中最主题的代码,转场动画的特效具体是什么样样子的注重是在此间达成的。要表明有些,一经达成了那几个代理方法,必须自身来编排具体的转场代码,系统的转场方式未有。如若不达成此措施,分界面无法跳转。参数transitionContext表示的是转场中满含的消息,全部转场进度中隐含的消息都足以从那当中获得,进而按照猎取的音讯设置转场效果。一般在这一个格局中落到实处代码的全体思路都以那样的,该办法具体实现由各样对应的步子。1、得到容器视图containerView2、获得对象视图toView3、toView增添到containerView上4、根据实际供给设置转场动画效果5、转场动画结束后必须调用[transitionContext completeTransition:YES];方法在第4步骤中得到了对象view,约等于B调节器的稻草黄View,在模态步入的时候先安装了前期的撼动角度,之后设置了一个动画片效果。

- animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext{ //1、获取容器view UIView *containerView = [transitionContext containerView]; //2、获取目标view /*UITransitionContextToViewKey UITransitionContextFromViewKey*/ UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey]; //3、把目标view添加到容器view中 [containerView addSubview:toView]; //4、实现动画 //4.1 设置初始值 toView.transform = CGAffineTransformMakeRotation; //4.2 通过动画的方式旋转到默认位置 //动画时间直接设置为转场动画的时间,系统默认时间是0.25s [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{ toView.transform = CGAffineTransformIdentity; } completion:^(BOOL finished) { //5、转场动画结束后必须调用[transitionContext completeTransition:YES];方法。 //如果不调用该方法,模态进入的界面将无法监听任何事件,界面直接不能进行交互 [transitionContext completeTransition:YES]; }];}

3.controller中管理代理方法

三、动画效果的贯彻

在详细批注动画效果以前,先讲一下动画片特效。B调控器中左右滑动分界面,红棕View会做相应角度的浮动。那么些动画效果其实正是在深蓝视图调整的view上增多了二个滑行的手势,然后依照手势横向移动的离开,调节器的view做一定角度的旋转,可是要丰富小心那几个旋转并非围绕淡绿View的骨干点旋转,而是围绕莲灰View下方宗旨线的某贰个点做旋转。这样就能提到三个知识点了:锚点anchorPoint。在成立视图调控器的View的时候,会调用loadView方法。何况安装了锚点为CGPointMake,关于锚点就相当的少说了,这么些事物用的依然比较多,有一点开荒经历应该都会精晓的。这里就给多个提出:设置叁个控件的地方,最棒使用UIView的center属性,只怕是CALayer的position属性。设置控件的轻重,最佳使用UIView的bounds属性。因为frame这特本性是依照控件的center、bounds、transform最终总计出来的,要是先是设置了frame,之后改换那个属性之一就能转移控件的任务。

- loadView{ //要调用此方法,不调用也无法触控 [super loadView]; //手动创建控制器的view self.view = [[UIView alloc]init]; self.view.backgroundColor = [UIColor blueColor]; self.view.layer.anchorPoint = CGPointMake; self.view.frame = [UIScreen mainScreen].bounds; //控制器view添加手势 UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panAction:)]; [self.view addGestureRecognizer:pan];}

假若查阅官方文书档案,CGAffineTransform是三个结构体,里面有如下七个参数:a, b, c, d,tx, ty,相关的形变均是由那多个参数调整,里面涉及到部分数学表达计算,关于这一个动画特效中的旋转角度的支配能够依附b值来判别旋转的角度,如若当b值的断然值超越某一临界值的时候,会再次回到到上一分界面。停止或收回击势的时候,假如偏移角度充足大,就能回到A调控器,借使非常不够大,就能够过来原样,突显在显示屏的正中间。要是处在拖动的经过中,B调整器浅黄view旋转的角度就做相应角度的浮动。

- panAction:(UIPanGestureRecognizer *)pan{ /* struct CGAffineTransform { CGFloat a, b, c, d; CGFloat tx, ty; };*/ //CGAffineTransform //CGAffineTransformMake(<#CGFloat a#>, <#CGFloat b#>, <#CGFloat c#>, <#CGFloat d#>, <#CGFloat tx#>, <#CGFloat ty#>) if (pan.state == UIGestureRecognizerStateEnded || pan.state == UIGestureRecognizerStateCancelled) { //根据transform的b值来判断旋转的情况,只要b值大于0.16,就让蓝色view掉下来 if (ABS(self.view.transform.b) > 0.16 ) { [UIView animateWithDuration:0.25 animations:^{ //dismiss控制器 [self dismissViewControllerAnimated:YES completion:nil]; }]; }else{ self.view.transform = CGAffineTransformIdentity; } }else{ CGFloat offsetX = [pan translationInView:self.view].x; CGFloat percent = offsetX / self.view.bounds.size.width; CGFloat radians = M_PI_4 * percent ; self.view.transform = CGAffineTransformMakeRotation; }}
  //这里是cell的代理方法,把需要做动画的图片和中心点以及点击的button传出来了
    func collectionViewCellDidClickAddButton(image: UIImage?, centerPoint: CGPoint, button: UIButton) {
        //先判断image是否有值
        guard let _ = image else
        {
            return
        }
        //创建动画的imageView
        let animationImageView = UIImageView(image:image)
        animationView = animationImageView
        animationImageView.center = centerPoint
        //把动画imageView添加到主窗口上
        XHRKeyWindow!.addSubview(animationImageView)
        //开始动画
        startAnimation(animationImageView,button: button)
    }

图片 15效果图

// cell的代理方法
protocol XHRCollectionViewCellDelegate : NSObjectProtocol
{
   func collectionViewCellDidClickAddButton(image:UIImage?,centerPoint:CGPoint,button:UIButton)
}
  • 拍卖点击事件
    在动画进程中禁止使用增多开关,待动画落成之后再张开,客商体验会好一点。

以下是动画片的切切实实贯彻代码

5.待动画达成后,试行到位后的事情逻辑

//这里把点击的button传过来是为了调整它的enable属性保证动画过程中按钮不可以被点击,加强用户体验
    private func startAnimation(imageView:UIImageView,button:UIButton)
    {
        //初始化旋转动画
        let animation = CABasicAnimation(keyPath: "transform.rotation.z")
        //设置属性
        animation.toValue = NSNumber(double: M_PI * 11)
        animation.duration = 1
        animation.cumulative = true;
        animation.repeatCount = 0;
        //初始化抛物线动画
        let pathAnimation = CAKeyframeAnimation(keyPath: "position")
        let startPoint = imageView.center
        let endPoint = (tabBarController as! XHRTabBarController).shoppCartCenter
        //抛物线的顶点,可以根据需求调整
        let controlPoint = CGPointMake(XHRScreenWidth * 0.5, startPoint.y - 100);
        //生成路径
        let path = CGPathCreateMutable();
        //描述路径
        CGPathMoveToPoint(path, nil, startPoint.x, startPoint.y)
        CGPathAddQuadCurveToPoint(path, nil, controlPoint.x, controlPoint.y, endPoint.x, endPoint.y)
        //设置属性
        pathAnimation.duration = 1
        pathAnimation.path = path
        //初始化动画组
        let animationGroup = CAAnimationGroup()
        animationGroup.animations = [animation,pathAnimation]
        animationGroup.duration = 1
        animationGroup.delegate = self
        //延时的目的是让view先做UIView动画然后再做layer动画
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (Int64)(100000000)), dispatch_get_main_queue(), {() -> Void in
            imageView.layer.addAnimation(animationGroup, forKey: nil)
        })
        UIView.animateWithDuration(1, animations: { () -> Void in
            imageView.bounds = CGRectMake(0, 0, 10, 10)
            imageView.center = endPoint
            }) { (_) -> Void in
              button.enabled = true
        }
    }
//用这个方法来计算购物车中心点的在主敞口上的坐标
    private func getShoppCartCenter()
    {
        for childView in tabBar.subviews
        {
            if childView.isKindOfClass(XHRShoppingCartButton.self)
            {
                //转换坐标系
                shoppCartCenter = tabBar.convertPoint(childView.center, toView: XHRKeyWindow)
                return
            }
        }
    }
  • 概念代理方法

本文由星彩网app下载发布于计算机编程,转载请注明出处:转场动画,可以很炫酷的转场动画

TAG标签: 星彩网app下载
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。