• 通过导航栏切换页面动画


    push动画

    #import <UIKit/UIKit.h>
    
    @interface ViewController : UIViewController <UINavigationControllerDelegate>
    
    @property (weak, nonatomic) IBOutlet UIButton *pushBtn;
    
    
    @end
    #import "ViewController.h"
    #import "Transition.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    - (void)viewWillAppear:(BOOL)animated {
        self.navigationController.delegate = self;
    }
    
    
    // 导航栏代理方法
    - (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC {
        if (operation == UINavigationControllerOperationPush) {
            return [Transition new];
        }else{
            return nil;
        }
    }
    
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    
    
    @end

    push动画对象

    #import <Foundation/Foundation.h>
    #import <UIKit/UIKit.h>
    #import "POP.h"
    
    @interface Transition : NSObject <UIViewControllerAnimatedTransitioning>
    
    @end
    #import "Transition.h"
    #import "ViewController.h"
    #import "TransferViewController.h"
    
    @interface Transition ()<CAAnimationDelegate>
    @property (nonatomic,strong)id<UIViewControllerContextTransitioning> transitionContext;
    @end
    
    @implementation Transition
    
    - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext{
        return  0.7f;
    }
    
    - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
        
        self.transitionContext = transitionContext;
        ViewController * fromVC = (ViewController *)[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
        TransferViewController * toVC = (TransferViewController *)[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
        UIView * contView = [transitionContext containerView];
        
        UIButton * button = fromVC.pushBtn;
        
        UIBezierPath * maskStartBP =  [UIBezierPath bezierPathWithOvalInRect:button.frame];
        [contView addSubview:fromVC.view];
        [contView addSubview:toVC.view];
        
        
        //创建两个圆形的 UIBezierPath 实例;一个是 button 的 size ,另外一个则拥有足够覆盖屏幕的半径。最终的动画则是在这两个贝塞尔路径之间进行的
        
        CGPoint finalPoint;
        //判断触发点在那个象限
        if(button.frame.origin.x > (toVC.view.bounds.size.width / 2)){
            if (button.frame.origin.y < (toVC.view.bounds.size.height / 2)) {
                //第一象限
                finalPoint = CGPointMake(button.center.x - 0, button.center.y - CGRectGetMaxY(toVC.view.bounds)+30);
            }else{
                //第四象限
                finalPoint = CGPointMake(button.center.x - 0, button.center.y - 0);
            }
        }else{
            if (button.frame.origin.y < (toVC.view.bounds.size.height / 2)) {
                //第二象限
                finalPoint = CGPointMake(button.center.x - CGRectGetMaxX(toVC.view.bounds), button.center.y - CGRectGetMaxY(toVC.view.bounds)+30);
            }else{
                //第三象限
                finalPoint = CGPointMake(button.center.x - CGRectGetMaxX(toVC.view.bounds), button.center.y - 0);
            }
        }
        
        CGFloat radius = sqrt((finalPoint.x * finalPoint.x) + (finalPoint.y * finalPoint.y));
        UIBezierPath * maskFinalBP = [UIBezierPath bezierPathWithOvalInRect:CGRectInset(button.frame, -radius, -radius)];
        
        
        //创建一个 CAShapeLayer 来负责展示圆形遮盖
        CAShapeLayer * maskLayer = [CAShapeLayer layer];
        maskLayer.path = maskFinalBP.CGPath; //将它的 path 指定为最终的 path 来避免在动画完成后会回弹
        toVC.view.layer.mask = maskLayer;
        
        CABasicAnimation * maskLayerAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
        maskLayerAnimation.fromValue = (__bridge id)(maskStartBP.CGPath);
        maskLayerAnimation.toValue = (__bridge id)((maskFinalBP.CGPath));
        maskLayerAnimation.duration = [self transitionDuration:transitionContext];
        maskLayerAnimation.timingFunction = [CAMediaTimingFunction  functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        maskLayerAnimation.delegate = self;
        
        [maskLayer addAnimation:maskLayerAnimation forKey:@"path"];
        
        
        /*  POP的弹框效果 CGPathRef
         
         CAKeyframeAnimation *keyFrame = [CAKeyframeAnimation animationWithKeyPath:@"path"];
         keyFrame.values = @[(__bridge id)(maskStartBP.CGPath),(__bridge id)(maskFinalBP.CGPath)];
         keyFrame.duration = 100.0f;
         keyFrame.additive = YES;
         keyFrame.removedOnCompletion = NO;
         keyFrame.fillMode = kCAFillModeForwards;
         
         
         [maskLayer addAnimation:keyFrame forKey:nil];
         maskLayer.speed = 0.0;
         
         
         POPAnimatableProperty* pop = [POPAnimatableProperty propertyWithName:@"timeOffset" initializer:^(POPMutableAnimatableProperty *prop) {
         // read value
         prop.readBlock = ^(CAShapeLayer *obj, CGFloat values[]) {
         values[0] = obj.timeOffset;
         };
         // write value
         prop.writeBlock = ^(CAShapeLayer *obj, const CGFloat values[]) {
         obj.timeOffset = values[0];
         };
         // dynamics threshold
         prop.threshold = 0.1;
         }];
         
         
         POPSpringAnimation *popSpring = [POPSpringAnimation animation];
         popSpring.fromValue = @(0.0);
         popSpring.toValue =  @(100.f);
         popSpring.springBounciness = 1.0;//弹性
         popSpring.springSpeed = 20.0;//速度
         popSpring.dynamicsTension = 700;//张力
         popSpring.dynamicsFriction = 5; // 摩擦力
         popSpring.dynamicsMass = 1;
         popSpring.property = pop;
         popSpring.delegate = self;
         [maskLayer pop_addAnimation:popSpring forKey:nil];
         
         */
        
        
        //    kPOPShapeLayerStrokeStart
        
        //创建一个关于 path 的 CABasicAnimation 动画来从 circleMaskPathInitial.CGPath 到 circleMaskPathFinal.CGPath 。同时指定它的 delegate 来在完成动画时做一些清除工作
    }
    
    - (void)pop_animationDidStop:(POPAnimation *)anim finished:(BOOL)finished {
        //告诉 iOS 这个 transition 完成
        [self.transitionContext completeTransition:![self. transitionContext transitionWasCancelled]];
        //清除 fromVC 的 mask
        [self.transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey].view.layer.mask = nil;
        [self.transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view.layer.mask = nil;
    }
    
    #pragma mark - CABasicAnimation的Delegate
    - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
        
        //告诉 iOS 这个 transition 完成
        [self.transitionContext completeTransition:![self. transitionContext transitionWasCancelled]];
        //清除 fromVC 的 mask
        [self.transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey].view.layer.mask = nil;
        [self.transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view.layer.mask = nil;
        
    }
    
    @end

    pop动画

    #import <UIKit/UIKit.h>
    
    @interface TransferViewController : UIViewController <UINavigationControllerDelegate>
    @property (weak, nonatomic) IBOutlet UIButton *popBtn;
    
    @end
    #import "TransferViewController.h"
    #import "InvertTransition.h"
    
    @interface TransferViewController ()
    
    @end
    
    @implementation TransferViewController
    {
        UIPercentDrivenInteractiveTransition * percentTransition;
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        UIScreenEdgePanGestureRecognizer * edgeGes = [[UIScreenEdgePanGestureRecognizer alloc]initWithTarget:self action:@selector(edgePan:)];
        edgeGes.edges = UIRectEdgeLeft;
        [self.view addGestureRecognizer:edgeGes];
    }
    
    -(void)viewWillAppear:(BOOL)animated{
        self.navigationController.delegate = self;
    }
    
    - (IBAction)clickToPop:(id)sender {
        [self.navigationController popViewControllerAnimated:YES];
    }
    
    - (id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>) animationController {
        return percentTransition;
    }
    
    - (id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC {
        if (operation == UINavigationControllerOperationPop) {
            InvertTransition * invert = [InvertTransition new];
            return invert;
        }else{
            return nil;
        }
    }
    
    - (void)edgePan:(UIPanGestureRecognizer *)recognizer{
        CGFloat per = [recognizer translationInView:self.view].x / (self.view.bounds.size.width);
        per = MIN(1.0,(MAX(0.0, per)));
        
        if (recognizer.state == UIGestureRecognizerStateBegan) {
            percentTransition = [[UIPercentDrivenInteractiveTransition alloc]init];
            [self.navigationController popViewControllerAnimated:YES];
        }else if (recognizer.state == UIGestureRecognizerStateChanged){
            [percentTransition updateInteractiveTransition:per];
        }else if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled){
            if (per > 0.3) {
                [percentTransition finishInteractiveTransition];
            }else{
                [percentTransition cancelInteractiveTransition];
            }
            percentTransition = nil;
        }
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    
    
    @end

    pop动画对象

    #import <Foundation/Foundation.h>
    #import <UIKit/UIKit.h>
    
    @interface InvertTransition : NSObject <UIViewControllerAnimatedTransitioning>
    
    @end
    #import "InvertTransition.h"
    #import "ViewController.h"
    #import "TransferViewController.h"
    
    @interface InvertTransition ()
    @property(nonatomic,strong)id<UIViewControllerContextTransitioning>transitionContext;
    @end
    
    @implementation InvertTransition
    - (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {
        return 0.7f;
    }
    
    - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
        
        self.transitionContext = transitionContext;
        TransferViewController * fromVC = (TransferViewController *)[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
        ViewController * toVC   = (ViewController *)[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
        UIView * contaionerView = [transitionContext containerView];
        UIButton * button = toVC.pushBtn;
        
        [contaionerView addSubview:toVC.view]; // 这个顺序不能变
        [contaionerView addSubview:fromVC.view];
        
        
        
        
        
        
        
        UIBezierPath * finalPath = [UIBezierPath bezierPathWithOvalInRect:button.frame];
        
        CGPoint finalPoint;
        
        //判断触发点在那个象限
        if(button.frame.origin.x > (toVC.view.bounds.size.width / 2)){
            if (button.frame.origin.y < (toVC.view.bounds.size.height / 2)) {
                //第一象限
                finalPoint = CGPointMake(button.center.x - 0, button.center.y - CGRectGetMaxY(toVC.view.bounds)+30);
            }else{
                //第四象限
                finalPoint = CGPointMake(button.center.x - 0, button.center.y - 0);
            }
        }else{
            if (button.frame.origin.y < (toVC.view.bounds.size.height / 2)) {
                //第二象限
                finalPoint = CGPointMake(button.center.x - CGRectGetMaxX(toVC.view.bounds), button.center.y - CGRectGetMaxY(toVC.view.bounds)+30);
            }else{
                //第三象限
                finalPoint = CGPointMake(button.center.x - CGRectGetMaxX(toVC.view.bounds), button.center.y - 0);
            }
        }
        
        CGFloat radius = sqrt(finalPoint.x * finalPoint.x + finalPoint.y * finalPoint.y);
        UIBezierPath *startPath = [UIBezierPath bezierPathWithOvalInRect:CGRectInset(button.frame, -radius, -radius)];
        
        CAShapeLayer *maskLayer = [CAShapeLayer layer];
        maskLayer.path = finalPath.CGPath;
        fromVC.view.layer.mask = maskLayer;
        
        
        CABasicAnimation *pingAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
        pingAnimation.fromValue = (__bridge id)(startPath.CGPath);
        pingAnimation.toValue   = (__bridge id)(finalPath.CGPath);
        pingAnimation.duration = [self transitionDuration:transitionContext];
        pingAnimation.timingFunction = [CAMediaTimingFunction  functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        
        pingAnimation.delegate = self;
        
        [maskLayer addAnimation:pingAnimation forKey:@"pingInvert"];
    }
    
    - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
        
        [self.transitionContext completeTransition:![self.transitionContext transitionWasCancelled]];
        [self.transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey].view.layer.mask = nil;
        [self.transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view.layer.mask = nil;
        
    }
    @end
  • 相关阅读:
    Zuul的核心源码解析
    基于Sentinel的服务保护
    Sentinel
    windows进行配置转发
    Hystrix断路器
    服务熔断Hystrix高级
    微服务架构的高并发问题
    Feign的高级配置
    倒排序原理和实例
    云计算技术的产生、概念、原理、应用和前景
  • 原文地址:https://www.cnblogs.com/fengmin/p/8176265.html
Copyright © 2020-2023  润新知