第一次在简书上面写东西,算是对自己的一些学习情况进行记录。如果有哪里表述的不太清楚请大家多多包涵。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)
}
}
第一次在简书上写东西,也不知道这个格式对不对,如果不对的话大家请到这里传送门