9

I have a circle-shaped view and have it rotate via the following code overriding touchesBegan(touches:, withEvent:) and touchesMoved(touches:, withEvent:).

var deltaAngle = CGFloat(0)
var startTransform: CGAffineTransform?

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
{
    let touchPoint = touches.first!.locationInView(view)

    let dx = touchPoint.x - view.center.x
    let dy = touchPoint.y - view.center.y

    deltaAngle = atan2(dy, dx)
    startTransform = arrowPickerView.transform
}

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?)
{
    let touchPoint = touches.first!.locationInView(view)

    let dx = touchPoint.x - view.center.x
    let dy = touchPoint.y - view.center.y
    let angle = atan2(dy, dx)
    let angleDifference = deltaAngle - angle
    let transform = CGAffineTransformRotate(startTransform!, -angleDifference)
    arrowPickerView.transform = transform
}

I want to override touchesEnded(touches:, withEvent:) to calculate the velocity and have the view naturally rotate a little (similar to continuous scrolling). I currently save the original transform and calculate the delta angle. How can I implement this? Thanks in advance!

Big_Mac
  • 2,975
  • 4
  • 20
  • 36
  • 1
    The velocity is distance divided by time so if you add an NSDate().timesince1970 in your touchesBegan and in your touchesEnd you can calculate the difference in seconds between the begin event and end event. The distance is just sqrt(dx^2 + dy^2). Or is that not the velocity you are looking for? Else ill rewrite as an answer below :) – Emptyless Apr 05 '16 at 10:35
  • I was looking just to handle kinetic scrolling to have it continue scrolling. If the user say scrolls super fast and then really slow and lets go then it will continue rotating at a speed faster than the last that it was rotating at. I put put an emphasis on velocity in the question, but it's all about kinetic scrolling – Big_Mac Apr 05 '16 at 19:45

1 Answers1

5

In my example below, the CGAffineTransformRotate depends on:

  • direction (if the user moves from left to right, up or down etc)
  • rotation (a factor dependent on the time between touchesBegan and touchesEnded)
  • PI

This creates an CGAffineTransformRotate and this rotates with duration 1 (s), to create a feel of kinetic scrolling the UIViewAnimationOptions.CurveEaseOut property is used

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {

    let touchPointEnd = touches.first!.locationInView(view)

    self.dateTouchesEnded = NSDate()

    let delay : NSTimeInterval = NSTimeInterval(0)

    let timeDelta : Double = self.dateTouchesEnded!.timeIntervalSince1970 - self.dateTouchesStarted!.timeIntervalSince1970

    let horizontalDistance : Double = Double(touchPointEnd.x - self.touchPointStart!.x)
    let verticalDistance : Double = Double(touchPointEnd.y - self.touchPointStart!.y)

    var direction : Double = 1
    if (fabs(horizontalDistance) > fabs(verticalDistance)) {
        if horizontalDistance > 0 {
            direction = -1
        }
    } else {
        if verticalDistance < 0 {
            direction = -1
        }
    }

    let rotation : Double = (0.1 / timeDelta < 0.99) ? 0.1 / timeDelta : 0.99

    let duration : NSTimeInterval = NSTimeInterval(1)
    UIView.animateWithDuration(duration, delay: delay, options: UIViewAnimationOptions.CurveEaseOut, animations: {
        let transform = CGAffineTransformRotate(self.imageView.transform, CGFloat(direction) * CGFloat(rotation) * CGFloat(M_PI))
        self.imageView.transform = transform
        }, completion: nil)

}

I added the variables to keep track of the start and end time of touches and added the CGPoint location of the touchesBegan function

var dateTouchesStarted : NSDate?
var dateTouchesEnded : NSDate?
var touchPointStart : CGPoint?

In touchesBegan i added:

self.touchPointStart = touchPoint

To set the variable as explained above.

Emptyless
  • 2,964
  • 3
  • 20
  • 30