美文网首页iOS开发
iOS 动画二十: Interactive Animations

iOS 动画二十: Interactive Animations

作者: _浅墨_ | 来源:发表于2018-09-13 21:23 被阅读38次
    An animation state machine

    UIViewPropertyAnimator 有三个属性可以标记当前动画交互状态:

    • isRunning :标记动画是否在运行。默认 false 。
    • isReversed :默认 false,动画从其开始状态播放到结束状态。 如果将此属性更改为 true ,则动画将反转方向并回放到其初始状态。
    • state :确定动画处于何种活动状态 。
    3D touch 交互动画

    AnimatorFactory.swift 新增方法:

    static func grow(view: UIVisualEffectView, blurView: UIVisualEffectView) -> UIViewPropertyAnimator {
        
        // 1
        view.contentView.alpha = 0
        view.transform = .identity
        // 2
        let animator = UIViewPropertyAnimator( duration: 0.5, curve: .easeIn)
        // 3
        animator.addAnimations {
          // blurView.effect = UIBlurEffect(style: UIBlurEffectStyle.dark)
          // view.transform = CGAffineTransform(scaleX: 1.5, y: 1.5)
          UIView.animateKeyframes(withDuration: 0.5, delay: 0.0, animations: {
            
            UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 1.0, animations: {
              blurView.effect = UIBlurEffect(style: .dark)
              view.transform = CGAffineTransform(scaleX: 1.5, y: 1.5)
            })
            
            UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5, animations: {
              view.transform = view.transform.rotated(by: -.pi/8)
            })
          })
        }
        // 4
        animator.addCompletion { position in
          switch position {
            case .start:
              blurView.effect = nil
            case .end:
              blurView.effect = UIBlurEffect(style: .dark)
            default: break
          }
        }
        return animator
      }
    

    WidgetsOwnerProtocol.swift

    import UIKit
    
    protocol WidgetsOwnerProtocol {
      var blurView: UIVisualEffectView {get}
    
      func startPreview(for: UIView)
      func updatePreview(percent: CGFloat)
      func finishPreview()
      func cancelPreview()
    }
    
    extension WidgetsOwnerProtocol {
      func startPreview(for forView: UIView) { }
      func updatePreview(percent: CGFloat) { }
      func finishPreview() { }
      func cancelPreview() { }
    }
    

    LockScreenViewController.swift extension WidgetsOwnerProtocol

    extension LockScreenViewController: WidgetsOwnerProtocol {
      
      func startPreview(for forView: UIView) {
        previewView?.removeFromSuperview()
        previewView = forView.snapshotView(afterScreenUpdates: false)
        view.insertSubview(previewView!, aboveSubview: blurView)
        
        previewView?.frame = forView.convert(forView.bounds, to: view)
        startFrame = previewView?.frame
        addEffectView(below: previewView!)
        
        previewAnimator = AnimatorFactory.grow(view: previewEffectView, blurView: blurView)
        
      }
      
      func updatePreview(percent: CGFloat) {
        previewAnimator?.fractionComplete = max(0.01, min(0.99, percent))
      }
      func cancelPreview() {
        if let previewAnimator = previewAnimator {
          previewAnimator.isReversed = true
          previewAnimator.startAnimation()
          
          previewAnimator.addCompletion { position in
            switch position {
            case .start:
              self.previewView?.removeFromSuperview()
              self.previewEffectView.removeFromSuperview()
            default: break
            }
          }
        }
      }
      
      func finishPreview() {
        
        // 1
        previewAnimator?.stopAnimation(false)
        // 2
        previewAnimator?.finishAnimation(at: .end)
        // 3
        previewAnimator = nil
        
        AnimatorFactory.complete(view: previewEffectView) .startAnimation()
        
        blurView.effect = UIBlurEffect(style: .dark)
        blurView.isUserInteractionEnabled = true
        blurView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(dismissMenu)))
      }
      
      func addEffectView(below forView: UIView) {
        previewEffectView.removeFromSuperview()
        previewEffectView.frame = forView.frame
        forView.superview?.insertSubview(previewEffectView, belowSubview: forView)
      }
      
      @objc func dismissMenu() {
        let reset = AnimatorFactory.reset(frame: startFrame!, view: previewEffectView, blurView: blurView)
        reset.addCompletion { _ in
          self.previewEffectView.removeFromSuperview()
          self.previewView?.removeFromSuperview()
          self.blurView.isUserInteractionEnabled = false
        }
        reset.startAnimation()
      }
    }
    

    demo 下载

    相关文章

      网友评论

        本文标题:iOS 动画二十: Interactive Animations

        本文链接:https://www.haomeiwen.com/subject/ivojgftx.html