8

What is the best way to implement a smooth reversing animation which tracks touches? I am referring to those animations in which, for example, if the user executes a swipe gesture some elements smoothly animate on screen, and others off, but if the user instead slowly drags a pan gesture back and forth the same objects will move forward/backward as a percent in accordance with the touch position. This is seen in many app intros and also in transitions. I have found

What I don't grasp - and I'm comfortable using CAAnimations and gestures - is how something can be both animated and interactive.

Typically, when I create an animation, I commit the animation and it goes from start to finish. While I could interrupt the animation as touches continue, that seems like it would be stilted.

On the other hand, moving things in response to user input is easy, but that is not animated.

How is the effect achieved where something can change according to an animation, but also have that exact same animation occur tied to touches, and yet still also have it so that although the animation reaches completion it doesn't really "finish" (become irreversible) unless the user releases touch, while at any point during interaction if the user releases panning then the animation either reverts backwards to its starting position or animates to completion depending on the last touch location and velocity. These requirements are baffling.

The glimpses of this technique I see all involve keyframe animations, but what I don't understand is where the touch events intersect with an animation to create these smooth effects I see.

Any tips, examples, or tutorials are most welcome.

Community
  • 1
  • 1
SG1
  • 2,871
  • 1
  • 29
  • 41
  • This question - http://stackoverflow.com/q/4720122/189804 - and its answers might help you. You can define an animation and move the animation along a path by changing the timeOffset property of an object conforming to CAMediaTiming. – Adam Eberbach Mar 27 '14 at 02:46

1 Answers1

14

What I don't grasp - and I'm comfortable using CAAnimations and gestures - is how something can be both animated and interactive.

It is because, having set up an animation, you can set that animation to any "frame" you wish. Thus you can track the animation in correspondence to the movement of a gesture.

The way this works is that an animation is a feature of the render tree, belonging to a CALayer. CALayer implements the CAMediaTiming protocol. The timeOffset of a CALayer thus determines what "frame" of an animation that layer displays. If a complex animation involves many different layers, no problem; just set the timeOffset of their mutual superlayer, to control the frame of the entire animation.

That in fact is exactly how the new iOS 7 interactive custom transition feature works (to which you rightly refer in your question). For instance, in this example code:

https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/iOS7bookExamples/bk2ch06p296customAnimation2/ch19p620customAnimation1/AppDelegate.m

... I keep updating the UIPercentDrivenInteractiveTransition to tell it how far through the gesture the user is, and the animation therefore tracks the gesture. Now ask yourself: how the heck is this possible???

Well, the UIPercentDrivenInteractiveTransition, in turn, behind the scenes, keeps adjusting the layer's timeOffset to portray the animation at the corresponding frame. (You can actually add logging code to my example to see that this is true.)

Moreover, when I end the gesture at an incomplete point, the animation either hurries to its end or runs backwards to its beginning - again, this is because of the CAMediaTiming protocol, which lets you change the speed of the animation, including a negative value to run it backwards.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • 1
    And here's a very nice tutorial on this topic: http://ronnqvi.st/controlling-animation-timing/ Once you understand about this - once the penny drops, as it were - a whole new world opens up. – matt Mar 27 '14 at 02:49
  • 1
    And see this tech note from Apple: https://developer.apple.com/library/ios/qa/qa1673/_index.html – matt Mar 27 '14 at 03:01
  • 1
    That tutorial is money. I can't believe how much simpler this actually is than I thought it would be. I would never have thought to use the timeOffset+speed properties this way, but now it's so obvious and yet brilliant. I feel I've done some pretty cool things in my apps but apps employing this technique always feel **so** smooth and well-polished to interact with. I can't wait to master it. Thank you very much Matt. – SG1 Mar 27 '14 at 03:59