Permalink
Browse files

switch to motionanimation

  • Loading branch information...
lkzhao committed Feb 8, 2016
1 parent 4eeae15 commit fc5824da8f224ab614b5b4c0cb8c4e0093f83b3a
Showing with 2,272 additions and 164 deletions.
  1. +2 −2 ElasticTransition.podspec
  2. +1 −1 ElasticTransition/EdgePanTransition.swift
  3. +75 −95 ElasticTransition/ElasticTransition.swift
  4. +2 −61 ElasticTransition/Util.swift
  5. +79 −2 ElasticTransitionExample.xcodeproj/project.pbxproj
  6. +10 −0 ElasticTransitionExample.xcworkspace/contents.xcworkspacedata
  7. +2 −0 ElasticTransitionExample/AppDelegate.swift
  8. +3 −3 ElasticTransitionExample/OptionsViewController.swift
  9. +3 −0 Podfile
  10. +10 −0 Podfile.lock
  11. +27 −0 Pods/Local Podspecs/MotionAnimation.podspec.json
  12. +10 −0 Pods/Manifest.lock
  13. +21 −0 Pods/MotionAnimation/LICENSE
  14. +43 −0 Pods/MotionAnimation/MotionAnimation/CGPoint+Util.swift
  15. +52 −0 Pods/MotionAnimation/MotionAnimation/LZPanGestureRecognizer.swift
  16. +65 −0 Pods/MotionAnimation/MotionAnimation/MotionAnimation.swift
  17. +149 −0 Pods/MotionAnimation/MotionAnimation/MotionAnimationPropertyState.swift
  18. +121 −0 Pods/MotionAnimation/MotionAnimation/MotionAnimator.swift
  19. +203 −0 Pods/MotionAnimation/MotionAnimation/NSObject+MotionAnimation.swift
  20. +38 −0 Pods/MotionAnimation/MotionAnimation/NSTimer.swift
  21. +42 −0 Pods/MotionAnimation/MotionAnimation/SpringValueAnimation.swift
  22. +159 −0 Pods/MotionAnimation/MotionAnimation/Types.swift
  23. +97 −0 Pods/MotionAnimation/MotionAnimation/ValueAnimation.swift
  24. +19 −0 Pods/MotionAnimation/MotionAnimation/time.swift
  25. +49 −0 Pods/MotionAnimation/README.md
  26. +546 −0 Pods/Pods.xcodeproj/project.pbxproj
  27. +60 −0 Pods/Pods.xcodeproj/xcshareddata/xcschemes/MotionAnimation.xcscheme
  28. +26 −0 Pods/Target Support Files/MotionAnimation/Info.plist
  29. +5 −0 Pods/Target Support Files/MotionAnimation/MotionAnimation-dummy.m
  30. +4 −0 Pods/Target Support Files/MotionAnimation/MotionAnimation-prefix.pch
  31. +6 −0 Pods/Target Support Files/MotionAnimation/MotionAnimation-umbrella.h
  32. +6 −0 Pods/Target Support Files/MotionAnimation/MotionAnimation.modulemap
  33. +6 −0 Pods/Target Support Files/MotionAnimation/MotionAnimation.xcconfig
  34. +26 −0 Pods/Target Support Files/Pods/Info.plist
  35. +28 −0 Pods/Target Support Files/Pods/Pods-acknowledgements.markdown
  36. +58 −0 Pods/Target Support Files/Pods/Pods-acknowledgements.plist
  37. +5 −0 Pods/Target Support Files/Pods/Pods-dummy.m
  38. +91 −0 Pods/Target Support Files/Pods/Pods-frameworks.sh
  39. +95 −0 Pods/Target Support Files/Pods/Pods-resources.sh
  40. +6 −0 Pods/Target Support Files/Pods/Pods-umbrella.h
  41. +8 −0 Pods/Target Support Files/Pods/Pods.debug.xcconfig
  42. +6 −0 Pods/Target Support Files/Pods/Pods.modulemap
  43. +8 −0 Pods/Target Support Files/Pods/Pods.release.xcconfig
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "ElasticTransition"
s.version = "2.0.1"
s.version = "2.1.0"
s.summary = "A UIKit custom modal transition that simulates an elastic drag. Written in Swift."
s.description = <<-DESC
@@ -23,5 +23,5 @@ Pod::Spec.new do |s|
s.source_files = 'ElasticTransition/*.swift'
# s.dependency 'pop', '~> 1.0'
s.dependency 'MotionAnimation', '~> 0.0.5'
end
@@ -26,7 +26,7 @@ SOFTWARE.
import UIKit
@available(iOS 7.0, *)
@available(iOS 8.0, *)
public class EdgePanTransition: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerInteractiveTransitioning, UIViewControllerTransitioningDelegate, UINavigationControllerDelegate{
public var panThreshold:CGFloat = 0.2
public var edge:Edge = .Right
@@ -25,12 +25,13 @@ SOFTWARE.
*/
import UIKit
import MotionAnimation
public enum ElasticTransitionBackgroundTransform:Int{
case None, Rotate, TranslateMid, TranslatePull, TranslatePush, Subtle
}
@available(iOS 7.0, *)
@available(iOS 8.0, *)
@objc
public protocol ElasticMenuTransitionDelegate{
optional var contentLength:CGFloat {get}
@@ -156,15 +157,28 @@ public class ElasticTransition: EdgePanTransition, UIGestureRecognizerDelegate{
}
// damping
public var stiffness:CGFloat = 60
public var stiffness:CGFloat = 0.2{
didSet{
stiffness = min(1.0, max(0.0, stiffness))
}
}
var maskLayer = CALayer()
var animator:UIDynamicAnimator!
var cc:DynamicItem!
var lc:DynamicItem!
var cb:CustomSnapBehavior!
var lb:CustomSnapBehavior!
var animationCenterStiffness:CGFloat {
return (stiffness + 0.5) * (interactive ? 550 : 420)
}
var animationSideStiffness:CGFloat {
return (stiffness + 0.5) * (interactive ? 400 : 300)
}
var animationThreshold:CGFloat {
return interactive ? 0.1 : 1
}
var animationDamping:CGFloat {
return (damping + 0.5) * 20
}
var contentLength:CGFloat = 0
var lastPoint:CGPoint = CGPointZero
var stickDistance:CGFloat{
@@ -239,9 +253,16 @@ public class ElasticTransition: EdgePanTransition, UIGestureRecognizerDelegate{
}
}
var multiValueObserverKey:MotionAnimationObserverKey!
public override init(){
super.init()
cc = DynamicItem(center: CGPointZero)
lc = DynamicItem(center: CGPointZero)
multiValueObserverKey = NSObject.m_addCallbackForAnyValueUpdated([cc:["center"],lc:["center"]]) { _ in
self.updateShape()
}
backgroundExitPanGestureRecognizer.delegate = self
backgroundExitPanGestureRecognizer.addTarget(self, action:"handleOffstagePan:")
foregroundExitPanGestureRecognizer.delegate = self
@@ -257,6 +278,10 @@ public class ElasticTransition: EdgePanTransition, UIGestureRecognizerDelegate{
shadowView.opaque = false
shadowView.layer.masksToBounds = false
}
deinit{
NSObject.m_removeMultiValueObserver(multiValueObserverKey)
}
func overlayTapped(tapGR:UITapGestureRecognizer){
if let vc = pushedControllers.last,
@@ -270,33 +295,30 @@ public class ElasticTransition: EdgePanTransition, UIGestureRecognizerDelegate{
override func update() {
super.update()
if cb != nil && lb != nil{
let initialPoint = self.finalPoint(!self.presenting)
let p = (useTranlation && interactive) ? translatedPoint() : dragPoint
switch edge{
case .Left:
cb.point = CGPointMake(p.x < contentLength ? p.x : (p.x-contentLength)/3+contentLength, dragPoint.y)
lb.point = CGPointMake(min(contentLength, p.distance(initialPoint) < stickDistance ? initialPoint.x : p.x), dragPoint.y)
case .Right:
let maxX = size.width - contentLength
cb.point = CGPointMake(p.x > maxX ? p.x : maxX - (maxX - p.x)/3, dragPoint.y)
lb.point = CGPointMake(max(maxX, p.distance(initialPoint) < stickDistance ? initialPoint.x : p.x), dragPoint.y)
case .Bottom:
let maxY = size.height - contentLength
cb.point = CGPointMake(dragPoint.x, p.y > maxY ? p.y : maxY - (maxY - p.y)/3)
lb.point = CGPointMake(dragPoint.x, max(maxY, p.distance(initialPoint) < stickDistance ? initialPoint.y : p.y))
case .Top:
cb.point = CGPointMake(dragPoint.x, p.y < contentLength ? p.y : (p.y-contentLength)/3+contentLength)
lb.point = CGPointMake(dragPoint.x, min(contentLength, p.distance(initialPoint) < stickDistance ? initialPoint.y : p.y))
}
let ccToPoint:CGPoint, lcToPoint:CGPoint
let initialPoint = self.finalPoint(!self.presenting)
let p = (useTranlation && interactive) ? translatedPoint() : dragPoint
switch edge{
case .Left:
ccToPoint = CGPointMake(p.x < contentLength ? p.x : (p.x-contentLength)/3+contentLength, dragPoint.y)
lcToPoint = CGPointMake(min(contentLength, p.distance(initialPoint) < stickDistance ? initialPoint.x : p.x), dragPoint.y)
case .Right:
let maxX = size.width - contentLength
ccToPoint = CGPointMake(p.x > maxX ? p.x : maxX - (maxX - p.x)/3, dragPoint.y)
lcToPoint = CGPointMake(max(maxX, p.distance(initialPoint) < stickDistance ? initialPoint.x : p.x), dragPoint.y)
case .Bottom:
let maxY = size.height - contentLength
ccToPoint = CGPointMake(dragPoint.x, p.y > maxY ? p.y : maxY - (maxY - p.y)/3)
lcToPoint = CGPointMake(dragPoint.x, max(maxY, p.distance(initialPoint) < stickDistance ? initialPoint.y : p.y))
case .Top:
ccToPoint = CGPointMake(dragPoint.x, p.y < contentLength ? p.y : (p.y-contentLength)/3+contentLength)
lcToPoint = CGPointMake(dragPoint.x, min(contentLength, p.distance(initialPoint) < stickDistance ? initialPoint.y : p.y))
}
cc.m_animate("center", to: ccToPoint, stiffness: animationCenterStiffness, damping: animationDamping, threshold: animationThreshold)
lc.m_animate("center", to: lcToPoint, stiffness: animationSideStiffness, damping: animationDamping, threshold: animationThreshold)
}
func updateShape(){
if animator == nil{
return
}
backView.layer.zPosition = 0
overlayView.layer.zPosition = 298
shadowView.layer.zPosition = 299
@@ -437,27 +459,25 @@ public class ElasticTransition: EdgePanTransition, UIGestureRecognizerDelegate{
container.backgroundColor = containerColor
}
// 6. setup uikitdynamic
setupDynamics()
// 6. setup MotionAnimation
let initialPoint = finalPoint(!presenting)
cc.center = initialPoint
lc.center = initialPoint
// 7. do a initial update (put everything into its place)
updateShape()
// if not doing an interactive transition, move the drag point to the final position
if !interactive{
let duration = self.transitionDuration(transitionContext)
lb.action = {
if self.animator != nil && self.animator.elapsedTime() >= duration {
self.cc.center = self.dragPoint
self.lc.center = self.dragPoint
self.updateShape()
self.clean(true)
}
}
dragPoint = self.startingPoint ?? container.center
dragPoint = finalPoint()
update()
cc.m_animate("center", to: dragPoint, stiffness: animationCenterStiffness, damping: animationDamping, threshold: animationThreshold)
lc.m_animate("center", to: dragPoint, stiffness: animationSideStiffness, damping: animationDamping, threshold: animationThreshold){
self.cc.center = self.dragPoint
self.lc.center = self.dragPoint
self.updateShape()
self.clean(true)
}
}
}
@@ -476,32 +496,8 @@ public class ElasticTransition: EdgePanTransition, UIGestureRecognizerDelegate{
shadowView.layer.masksToBounds = true
}
}
func setupDynamics(){
animator = UIDynamicAnimator(referenceView: container)
let initialPoint = finalPoint(!presenting)
cc = DynamicItem(center: initialPoint)
lc = DynamicItem(center: initialPoint)
cb = CustomSnapBehavior(item: cc, point: dragPoint)
cb.damping = damping
cb.frequency = max(stiffness,1)/25
lb = CustomSnapBehavior(item: lc, point: dragPoint)
lb.damping = min(1.0, damping * 1.5)
lb.frequency = max(stiffness,1)/25
update()
cb.action = {
self.updateShape()
}
animator.addBehavior(cb)
animator.addBehavior(lb)
}
override func clean(finished:Bool){
animator.removeAllBehaviors()
animator = nil
frontView.layer.zPosition = 0
if navigation{
shadowView.removeFromSuperview()
@@ -517,43 +513,27 @@ public class ElasticTransition: EdgePanTransition, UIGestureRecognizerDelegate{
override func cancelInteractiveTransition(){
super.cancelInteractiveTransition()
let finalPoint = self.finalPoint(!self.presenting)
let finalPoint = self.finalPoint(!presenting)
cb.point = finalPoint
lb.point = finalPoint
lb.action = {
if finalPoint.distance(self.cc.center) < 1 &&
finalPoint.distance(self.lc.center) < 1 &&
self.lastPoint.distance(self.cc.center) < 0.05{
self.cc.center = finalPoint
self.lc.center = finalPoint
self.updateShape()
self.clean(false)
}else{
self.updateShape()
}
self.lastPoint = self.cc.center
lc.m_animate("center", to: finalPoint, stiffness: animationSideStiffness, damping: animationDamping, threshold: animationThreshold)
cc.m_animate("center", to: finalPoint, stiffness: animationCenterStiffness, damping: animationDamping, threshold: animationThreshold){
self.cc.center = finalPoint
self.lc.center = finalPoint
self.updateShape()
self.clean(false)
}
}
override func finishInteractiveTransition(){
super.finishInteractiveTransition()
let finalPoint = self.finalPoint()
cb.point = finalPoint
lb.point = finalPoint
lb.action = {
if finalPoint.distance(self.cc.center) < 1 &&
finalPoint.distance(self.lc.center) < 1 &&
self.lastPoint.distance(self.cc.center) < 0.05{
self.cc.center = finalPoint
self.lc.center = finalPoint
self.updateShape()
self.clean(true)
}else{
self.updateShape()
}
self.lastPoint = self.cc.center
lc.m_animate("center", to: finalPoint, stiffness: animationSideStiffness, damping: animationDamping, threshold: animationThreshold)
cc.m_animate("center", to: finalPoint, stiffness: animationCenterStiffness, damping: animationDamping, threshold: animationThreshold){
self.cc.center = finalPoint
self.lc.center = finalPoint
self.updateShape()
self.clean(true)
}
}
@@ -573,7 +553,7 @@ public class ElasticTransition: EdgePanTransition, UIGestureRecognizerDelegate{
}
override public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return NSTimeInterval((abs(damping - 0.2) * 0.5 + 0.6)/(max(stiffness,1)/40))
return 0.7
}
}
@@ -70,69 +70,10 @@ extension CGPoint{
}
}
class DynamicItem:NSObject, UIDynamicItem{
class DynamicItem:NSObject{
var center: CGPoint = CGPointZero
var bounds: CGRect = CGRectMake(0, 0, 1, 1)
var transform: CGAffineTransform = CGAffineTransformIdentity
init(center:CGPoint) {
self.center = center
super.init()
}
}
class CustomSnapBehavior:UIDynamicBehavior {
var ab1:UIAttachmentBehavior!
var ab2:UIAttachmentBehavior!
var ab3:UIAttachmentBehavior!
var ab4:UIAttachmentBehavior!
var item:UIDynamicItem
var frequency:CGFloat = 1{
didSet{
ab1.frequency = frequency
ab2.frequency = frequency
ab3.frequency = frequency
ab4.frequency = frequency
}
}
var damping:CGFloat = 0{
didSet{
ab1.damping = damping
ab2.damping = damping
ab3.damping = damping
ab4.damping = damping
}
}
var point:CGPoint{
didSet{
updatePoints()
}
}
func updatePoints(){
ab1.anchorPoint = point.translate(50, dy: 0)
ab2.anchorPoint = point.translate(-50, dy: 0)
ab3.anchorPoint = point.translate(0, dy: 50)
ab4.anchorPoint = point.translate(0, dy: -50)
}
init(item:UIDynamicItem, point:CGPoint, useSnap:Bool = false) {
self.item = item
self.point = point
super.init()
ab1 = UIAttachmentBehavior(item: item, attachedToAnchor: point)
addChildBehavior(ab1)
ab2 = UIAttachmentBehavior(item: item, attachedToAnchor: point)
addChildBehavior(ab2)
ab3 = UIAttachmentBehavior(item: item, attachedToAnchor: point)
addChildBehavior(ab3)
ab4 = UIAttachmentBehavior(item: item, attachedToAnchor: point)
addChildBehavior(ab4)
ab1.length = 50
ab2.length = 50
ab3.length = 50
ab4.length = 50
updatePoints()
}
}
}
Oops, something went wrong.

0 comments on commit fc5824d

Please sign in to comment.