From de86cf86b6c7379e3d1b0bf0bd9306f6970d387d Mon Sep 17 00:00:00 2001 From: Victor Baro Date: Wed, 6 May 2015 00:33:47 +0100 Subject: [PATCH] initial commit --- .../xcschemes/FrictionCurves.xcscheme | 69 ++++++++ FrictionCurves/Base.lproj/Main.storyboard | 155 ++++++++++++++---- FrictionCurves/FirstViewController.swift | 70 +++++++- FrictionCurves/SecondViewController.swift | 37 ++++- 4 files changed, 289 insertions(+), 42 deletions(-) diff --git a/FrictionCurves.xcodeproj/xcuserdata/victorbaro.xcuserdatad/xcschemes/FrictionCurves.xcscheme b/FrictionCurves.xcodeproj/xcuserdata/victorbaro.xcuserdatad/xcschemes/FrictionCurves.xcscheme index 6b19159..ad8e0b0 100644 --- a/FrictionCurves.xcodeproj/xcuserdata/victorbaro.xcuserdatad/xcschemes/FrictionCurves.xcscheme +++ b/FrictionCurves.xcodeproj/xcuserdata/victorbaro.xcuserdatad/xcschemes/FrictionCurves.xcscheme @@ -5,6 +5,36 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -32,6 +91,16 @@ useCustomWorkingDirectory = "NO" buildConfiguration = "Release" debugDocumentVersioning = "YES"> + + + + diff --git a/FrictionCurves/Base.lproj/Main.storyboard b/FrictionCurves/Base.lproj/Main.storyboard index 77ba998..f49ed79 100644 --- a/FrictionCurves/Base.lproj/Main.storyboard +++ b/FrictionCurves/Base.lproj/Main.storyboard @@ -1,13 +1,14 @@ - + - + + - + @@ -16,38 +17,109 @@ - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -56,31 +128,46 @@ - - + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + diff --git a/FrictionCurves/FirstViewController.swift b/FrictionCurves/FirstViewController.swift index 2bf6792..79318dc 100644 --- a/FrictionCurves/FirstViewController.swift +++ b/FrictionCurves/FirstViewController.swift @@ -10,16 +10,78 @@ import UIKit class FirstViewController: UIViewController { + @IBOutlet weak var topViewLeadingConstraint: NSLayoutConstraint! + @IBOutlet weak var middleViewLeadingConstraint: NSLayoutConstraint! + @IBOutlet weak var bottomLeadingConstraint: NSLayoutConstraint! + + @IBOutlet weak var movingView: UIView! + @IBOutlet weak var movingViewLeadingConstraint: NSLayoutConstraint! + + let horizontalLimit : CGFloat = 160.0 + override func viewDidLoad() { super.viewDidLoad() - // Do any additional setup after loading the view, typically from a nib. + addVerticalLine() + } + @IBAction func viewDragged(sender: UIPanGestureRecognizer) { + let xPosition = sender.locationInView(view).x + movingViewLeadingConstraint.constant = linearConstraintValueForXPoisition(xPosition) + + if (hasExceededVerticalLine(xPosition)) { + topViewLeadingConstraint.constant = sqrtConstraintValueForXPoisition(xPosition) + middleViewLeadingConstraint.constant = lognConstraintValueForXPoisition(xPosition) + bottomLeadingConstraint.constant = powConstraintValueForXPoisition(xPosition) + + if(sender.state == UIGestureRecognizerState.Ended ){ + movingViewLeadingConstraint.constant = finalConstraintValue() + topViewLeadingConstraint.constant = finalConstraintValue() + middleViewLeadingConstraint.constant = finalConstraintValue() + bottomLeadingConstraint.constant = finalConstraintValue() + } + } else { + topViewLeadingConstraint.constant = linearConstraintValueForXPoisition(xPosition) + middleViewLeadingConstraint.constant = linearConstraintValueForXPoisition(xPosition) + bottomLeadingConstraint.constant = linearConstraintValueForXPoisition(xPosition) + } - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. } + func linearConstraintValueForXPoisition(xPosition : CGFloat) -> CGFloat { + return xPosition - CGRectGetWidth(movingView.frame)/2 + } + func sqrtConstraintValueForXPoisition(xPosition : CGFloat) -> CGFloat { + let linearValue = linearConstraintValueForXPoisition(xPosition) + return finalConstraintValue() + sqrt(linearValue - finalConstraintValue()) + } + func powConstraintValueForXPoisition(xPosition : CGFloat) -> CGFloat { + let linearValue = linearConstraintValueForXPoisition(xPosition) + let powValue = pow(linearValue/finalConstraintValue(), 4.0) + return linearValue - powValue + } + func lognConstraintValueForXPoisition(xPosition : CGFloat) -> CGFloat { + let linearValue = linearConstraintValueForXPoisition(xPosition) + return finalConstraintValue() * (1 + log10(linearValue/finalConstraintValue())) + } + + +//Helping methods + func addVerticalLine() { + let lineThickness : CGFloat = 2.0; + let lineFrame = CGRectMake(horizontalLimit - lineThickness/2, 0, lineThickness, CGRectGetHeight(view.frame)) + var verticalLineView : UIView = UIView (frame: lineFrame) + verticalLineView.backgroundColor = UIColor.redColor() + view.addSubview(verticalLineView) + } + + func finalConstraintValue() -> CGFloat { + let viewWidth = CGRectGetWidth(movingView.frame) + return horizontalLimit - viewWidth/2 + } + func hasExceededVerticalLine(xPosition : CGFloat) -> Bool { + return xPosition > horizontalLimit + } + } diff --git a/FrictionCurves/SecondViewController.swift b/FrictionCurves/SecondViewController.swift index f417b62..d3c8daa 100644 --- a/FrictionCurves/SecondViewController.swift +++ b/FrictionCurves/SecondViewController.swift @@ -10,16 +10,45 @@ import UIKit class SecondViewController: UIViewController { + + @IBOutlet weak var topViewConstraint: NSLayoutConstraint! + let verticalLimit : CGFloat = -200 + var totalTranslation : CGFloat = -200 + override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. } - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. + @IBAction func viewDragged(sender: UIPanGestureRecognizer) { + let yTranslation = sender.translationInView(view).y + + if (hasExceededVerticalLimit(topViewConstraint.constant)){ + totalTranslation += yTranslation + topViewConstraint.constant = logConstraintValueForYPoisition(totalTranslation) + if(sender.state == UIGestureRecognizerState.Ended ){ + animateViewBackToLimit() + } + } else { + topViewConstraint.constant += yTranslation + } + sender.setTranslation(CGPointZero, inView: view) } - + + func hasExceededVerticalLimit(yPosition : CGFloat) -> Bool { + return yPosition < verticalLimit + } + func logConstraintValueForYPoisition(yPosition : CGFloat) -> CGFloat { + return verticalLimit * (1 + log10(yPosition/verticalLimit)) + } + func animateViewBackToLimit() { + self.topViewConstraint.constant = self.verticalLimit + + UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 0.3, initialSpringVelocity: 10, options: UIViewAnimationOptions.AllowUserInteraction, animations: { () -> Void in + self.view.layoutIfNeeded() + self.totalTranslation = -200 + }, completion: nil) + } }