美文网首页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