扩大动画效果,希望你喜欢

1. view 分类: 动画类抽取

  • 效果图
扩大动画效果,希望你喜欢_第1张图片
效果图.gif
import UIKit

var kDefaultLayerBgColor = UIColor.cyanColor().CGColor

// 扩大方法  CGRectInset(rect, dx, dy) -> 以原rect为中心,再参考dx,dy,进行缩放或者放大, -radius 放大
func expend(center: CGPoint, radius: CGFloat) -> CGRect{
    return CGRectInset(CGRect(origin: center, size: CGSizeZero), -radius,  -radius)
}

extension UIView{
    
    /**
     view 执行圆形动画效果
     
     - parameter durantion:        动画时长
     - parameter blewLayer:        扩大的 layer,在 哪个 layer下面:如果 传nil ,就添加到当前视图 的最前面(遮挡下面的layer)
     - parameter circleCenter:     圆心
     - parameter isOpen:           是打开,还是关闭效果
     - parameter animationHandle:  进行动画事的处理事件  : layer -》 扩大 遮盖层layer,我们可以对其进行 处理,如:进行透明度 等动画效果,等等
     - parameter completionHandle: 整个动画完成处理事件
     */
    func animateCircleAnimation(duration durantion: NSTimeInterval,  blewLayer: CALayer? = nil, circleCenter: CGPoint, isOpen: Bool, @noescape animationHandle: (layer: CALayer)-> Void, completionHandle: ((Bool) -> Void)? = nil){
        
        let fillLayer = CALayer()
        fillLayer.frame = self.bounds
   
        if let _ = blewLayer{
            layer.insertSublayer(fillLayer, below: blewLayer)
            
        }else{
            layer.addSublayer(fillLayer)
        }
        
        // 获取在 holdView 的中心点
        let center = circleCenter
        
        // 利用勾股定理,求出 圆半径
        let x = max(center.x, frame.width - center.x)
        let y = max(center.y, frame.height - center.y)
        
        let circleRadius = sqrt(x*x + y*y)
        
        // 创建动画对象
        var animation: CircleShowAnimator
        
        if isOpen{
            fillLayer.opacity = 0.99
            animation = CircleShowAnimator(layer: fillLayer, center: center, startRadius: 0, endRadius: circleRadius)
        }else{
            fillLayer.opacity = 0.99
            animation = CircleShowAnimator(layer: fillLayer, center: center, startRadius: circleRadius, endRadius: 0)
        }
        
        animation.duration = durantion
        animation.completion = { layer in
                fillLayer.removeFromSuperlayer()
    
                if let _ = completionHandle{
                    completionHandle!(true)
                }
            
        }
        
        animation.show()
        animationHandle(layer: animation.layer)
    }
}

class CircleShowAnimator {
    
    var completion: () -> Void = {}
    
    var layer: CALayer
    private let mask: CAShapeLayer
    private let animation: CABasicAnimation
    
    var duration: CFTimeInterval {
        get { return animation.duration }
        set(value) { animation.duration = value }
    }
    
    var timingFunction: CAMediaTimingFunction! {
        get { return animation.timingFunction }
        set(value) { animation.timingFunction = value }
    }
    
    
    init(layer: CALayer, center: CGPoint, startRadius: CGFloat, endRadius: CGFloat, isOpen: Bool = false){
        
        
        // 大小圆路径
        let startCirclePath = CGPathCreateWithEllipseInRect(expend(center, radius: startRadius), nil)
        let endCirclePath = CGPathCreateWithEllipseInRect(expend(center, radius: endRadius), nil)
        
        var startPath = startCirclePath, endPath = endCirclePath
        
        if isOpen{
            var path = CGPathCreateMutable()
            CGPathAddRect(path, nil, layer.bounds)
            CGPathAddPath(path, nil, startCirclePath)
            
            startPath = path
            
            path = CGPathCreateMutable()
            CGPathAddRect(path, nil, layer.bounds)
            CGPathAddPath(path, nil, endCirclePath)
            
            endPath = path
        }
        
        self.layer = layer
        self.layer.backgroundColor = kDefaultLayerBgColor
        
        // CAShapeLayer
        mask = CAShapeLayer()
        mask.path = endPath
        mask.fillRule = kCAFillRuleEvenOdd
        
        animation = CABasicAnimation(keyPath: "path")
        animation.fromValue = startPath
        animation.toValue = endPath
        
        animation.duration = duration
        
        animation.delegate = AnimationDelegate(completion: { () -> Void in
            layer.mask = nil
            self.completion()
            self.animation.delegate = nil
        })
    }
    
    func show(){
        layer.mask = mask
        mask.frame = layer.bounds
        mask.addAnimation(animation, forKey: "circleAnima")
    }
}

class AnimationDelegate{
    
    private let completion: () -> Void
    
    init(completion: () -> Void) {
        self.completion = completion
    }
    
    dynamic func animationDidStop(_: CAAnimation, finished: Bool) {
        completion()
    }
}

2. 使用


import UIKit

class CircleAnimationViewController: UIViewController {

    lazy var startBtn: UIButton = {
       
        let btn = UIButton()
        btn.size = CGSizeMake(200, 54)
        btn.alpha = 0.8
        
        btn.layer.borderColor = UIColor.orangeColor().CGColor
        btn.layer.borderWidth = 1
        btn.layer.cornerRadius = 27
        btn.layer.masksToBounds = true
        
        btn.setTitle("点击", forState: .Normal)
        btn.setTitle("跳转", forState: UIControlState.Highlighted)
        
        btn.backgroundColor = UIColor.blackColor()
        
        btn.addTarget(self, action: "startBtnClick", forControlEvents: UIControlEvents.TouchDown)
        
        btn.center = self.view.center

        return btn
    }()
    
    lazy var LoadBtn: UIButton = {
        
        let btn = UIButton()
        btn.frame = CGRectMake(20, 80, 60, 60)
        btn.alpha = 0.8
        
        btn.layer.borderColor = UIColor.orangeColor().CGColor
        btn.layer.borderWidth = 1
        btn.layer.cornerRadius = btn.frame.size.width / 2
        btn.layer.masksToBounds = true
        
        btn.setTitle("点击", forState: .Normal)
    
        btn.backgroundColor = UIColor.blueColor()
        
        btn.addTarget(self, action: "enterBtnClick:", forControlEvents: UIControlEvents.TouchUpInside)
     
        return btn
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.view.backgroundColor = UIColor.whiteColor()
        
        self.view.addSubview(self.startBtn)
        self.view.addSubview(LoadBtn)
    }

    
    func startBtnClick(){
        
        let center = CGPoint(x: self.startBtn.bounds.midX, y: self.startBtn.bounds.midY)
        
        // 点击按钮进行 扩大动画,动画结束 切换 视图
        self.startBtn.animateCircleAnimation(duration: 0.5, blewLayer: self.startBtn.imageView?.layer, circleCenter: center, isOpen: true, animationHandle: { (layer) -> Void in
            
            // 修改 layer 的背景颜色
            layer.backgroundColor = UIColor.greenColor().CGColor
            
            layer.opacity = 0
            
            let opacityAnim = CABasicAnimation(keyPath: "opacity")
            opacityAnim.fromValue = 0.9
            opacityAnim.toValue = 0.6
            opacityAnim.duration = 0.5
          
            layer.addAnimation(opacityAnim, forKey: "opacity")
            
        }) { (_) -> Void in
            self.navigationController?.pushViewController(Nav3ViewController(), animated: true)
        }
    }
    
    func enterBtnClick(sender: UIButton){
        
        // 效果一: 扩大动画 在 按钮 下面  blewLayer: sender.layer, 按钮 未被遮盖效果
        self.view.animateCircleAnimation(duration: 0.5, blewLayer: sender.layer, circleCenter: sender.center, isOpen: true, animationHandle: { (layer) -> Void in
            
        }) { (_) -> Void in
            
            self.navigationController?.pushViewController(Nav3ViewController(), animated: false)
        }
        
        
        // 效果而: 扩大 动画在按钮上面 ,  blewLayer 参数未传值, 按钮被遮盖 的效果
        /*
         
         self.view.animateCircleAnimation(duration: 0.5, circleCenter: sender.center, isOpen: true, animationHandle: { (layer) -> Void in
         
         }) { (_) -> Void in
         
         self.navigationController?.pushViewController(Nav3ViewController(), animated: false)
         }
         
        */
    }
}
  • Nav3ViewController 部分代码
// 返回按钮
lazy var backBtn: UIButton = {
        
        let btn = UIButton(frame: CGRectMake(15, 24, 27, 27))
        btn.addTarget(self, action: "backBtnClick:", forControlEvents: UIControlEvents.TouchUpInside)
        
        btn.setImage(UIImage(named: "back_normal"), forState: UIControlState.Normal)
        
        return btn
        }()

// 2. 返回按钮事件:处理, 退出当前控制器,缩小动画

   func backBtnClick(sender: UIButton){
        
        self.view.animateCircleAnimation(duration: 0.5, blewLayer: sender.layer, circleCenter: sender.center, isOpen: false, animationHandle: { (layer) -> Void in
            
//             self.tableView.hidden = true
//             self.topScaleImageView.hidden = true
            
            }) { (_) -> Void in
                self.navigationController?.popViewControllerAnimated(false)
        }
  • 当然 如果你觉得 圆形扩大路径不是你想要的效果,你可以 尝试 改变 CGPath,就动态设定 属于你的 扩大缩小动画

你可能感兴趣的:(扩大动画效果,希望你喜欢)