自定义转场动画--蒙板(Swift)

第一次在简书上面写东西,算是对自己的一些学习情况进行记录。如果有哪里表述的不太清楚请大家多多包涵。929562459这是我的QQ大家可以一起进行一些交流。
最近在做一个项目,在播放视频的时候push(这个viewController暂称为A)到播放视频的viewController(暂称为B)时需要一个过渡动画,手上没有相对应的视频,给大家口述一下:从A push 到B的时候从屏幕右下角开始出现一个四分之一的圆形。随着圆形的扩大A消失B显示出来。从B pop到A的时候恰好是相反的。在使用蒙板做的时候需要记住一点就可以了给一个UIView或者UIView的子类添加一个蒙板的时候,该UIView只会显示和该蒙板重合的地方,其余的部分则是这个UIView下层的UIView. 举个例子假设一个ViewController的view的背景色为红色,给它添加一个子视图,子视图的frame为(0,0,view.bounds.size.width,view.bounds.size.height)设置背景色为黄色。给子视图添加一个蒙板层,蒙版的宽度和子视图的宽度相同,高度为子视图的一半,这时看到的效果则是一半为红色一半为黄色。下面是部分代码:

class A : UIViewController, UINavigationControllerDelegate {
  let popAnimation = PopViewAnimation()  //下面给出这个动画的实现
  override func viewDidLoad() {
    //......
     navigationController.delegate = self
    //......
  }
func navigationController(navigationController: UINavigationController,animationControllerForOperation operation: UINavigationControllerOperation,fromViewController fromVC: UIViewController,toViewController toVC: UIViewController)->UIViewControllerAnimatedTransitioning? {
    //在这里需要注意的是如果从A 可以push 到B C D 等多个ViewController 但是只有从A push 到B时才有动画可以在下面加上
    if operation == .Push { // && toVC is xxxViewController(目标ViewController)
      return popAnimation
    }
    return nil
   }
}
//跳转动画的实现
class PopViewAnimation : NSObject,UIViewControllerAnimatedTransitioning {
    
    // 屏幕宽度
    let width: CGFloat = UIScreen.masinScreen().bounds.size.width
    //屏幕高度
    let height: CGFloat = UIScreen.mainScreen().bounds.size.height
    //遮罩层
    let maskLayer = CAShapeLayer()
    //设置遮罩层初始路径大小
    let originFrame = CGRect(x:width,y:height,width:1,height:1)
    var radio: CGFloat = 0  
    private var transitionContext : UIViewControllerContextTransitioning!

    func transitionDuration(transitionContext:             UIViewControllerContextTransitioning?) -> NSTimeInterval { 
    return 2 //动画持续的时间
  }

  func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
    
    //圆形半径  勾股定理哈哈 圆形半径为屏幕对角宽度 四分之一圆刚好可以遮盖屏幕
    radio = sqrt(width*width + height*height)

    let originPath = UIBezierPath(OvalInRect:originFrame).CGPath
    //CGRectInset 有三个参数 rect dx dy 将rect的宽度的和高度缩小多少倍,因为我们在这里需要扩大多少倍所以选择-radio
    let destPath = UIBezierPath(OvalInRect:CGRectInset(originFrame,dx:-radio,dy:-radio)).CGPath

    //A ViewController
     let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) 

    //B ViewController
    let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
    maskLayer.path = originPath    
    toVC.view.layer.mask = maskLayer  

    //在这里需要注意了,因为我们需要在动画执行的过程中A慢慢消失,B慢慢出现,根据上面所说的遮罩层没有遮罩的地方将显示该View下面的View.在这里A和B的层级关系就是B在A的上面,当B的罩着层慢慢扩大时,随着B慢慢显示A逐渐消失,明白这点就容易多了.

    //将B的View添加到A的View上面
   // transitionContext.containerView()?.insertSubview(toVC.view, aboveSubview: fromVC.view)
    //将B 的View移动到最上层
    transitionContext.containerView()?.bringSubViewToFront(toVC.view)
    self.transitionContext = transitionContext    

    let animation = CABasicAnimation(keyPath: "path")
    animation.fromValue = originPath 
    animation.toValue = destPath 
    animation.duration = 2.0
    animation.delegate = self
    maskLayer.addAnimation(animation, forKey: "path")

  }
  
  //动画执行完成后执行
  override func animationDidStop(anim: CAAnimation, finished flag: Bool) {
    //上面那个动画执行完成后,maskLayer会返回到执行动画前的状态,有 属性可以设置保存执行完动画的状态。在这里我重新设置为执行完动画后的状态
    maskLayer.path = UIBezierPath(ovalInRect:CGRectInset(originFrame, -radio, -radio)).CGPath
    //用于通知动画执行完成
    transitionContext.completeTransition(true)
  }
}

第一次在简书上写东西,也不知道这个格式对不对,如果不对的话大家请到这里传送门

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,417评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,921评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,850评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,945评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,069评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,188评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,239评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,994评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,409评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,735评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,898评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,578评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,205评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,916评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,156评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,722评论 2 363
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,781评论 2 351

推荐阅读更多精彩内容