The Science Behind Snapping Scroll – Part II: Animation & Logic

It’s been ages since my last article, especially in light of the breakneck speed with which prototyping with Quartz Composer is evolving. People contribute so much it’s hard to keep up with everything that’s going on. Nevertheless, I hope the basics I cover in the second part of my Snapping Scroll tutorial will still prove to be helpful to you.

Before we start building, I’d like to show you one simple trick that we’ll use later in the tutorial. It can be very useful, not only for our Snapping Scroll patch, but animation in general.

One Way Animation

Let’s look at the Classic Animation patch. The way it works is very simple. You set the duration and easing curve and it will return the intermediate values over time until it reaches the destination value (Number that you also set in the patch). It will hold the value until you change it again. The common usage for the patch is back and forth animation, created by setting the Number to 1 and 0 alternately using a Switch patch (Show/Hide, FadeIn/FadeOut etc.).

Obviously, that’s not the case in Snapping Scroll. We don’t know the Start and End values of our animation. We want our Layer to animate between two dynamically set points – the point at which it was released and the point to which it should snap. In other words, for our convenience, it should always be a 0 to 1 animation.

But… I know! There’s no simple way to reset the Classic Animation patch. Once it reaches the Number, it holds it until you change it again (I guess we could set Duration to 0, reset the number, and then set Duration back to whatever it was. That sounds fairly complicated, though).

Fortunately for us, there’s a simple workaround. We can modify the output so that it always goes from 0 to 1.

We’ll use a Mathematical Expression patch and the formula:

on_off ? progress : -progress+1

When the switch is set to ON (1), we leave the progress as it is. When the switch is turned OFF (0) we use -progress+1 as the output. Now the animation always goes from 0 to 1, regardless of whether Switch inputs 0 or 1. Animation Output

Snapping Scroll tutorial – Part 1 of 2:

Now, let’s pick up where we left off. But, before we move on, we need to fix something in our Step_4 file. I used the Click output from the Interaction 2 patch to detect the release of the mouse button. Later I discovered that Click will not output 1 if you release the button outside of the Layer bounds. It’s safer to use the Drag output only with the Pulse patch and Detection Mode set to Trailing Edge, so be sure to introduce these changes. Also, let’s create Macro and label the outputs properly to add a little clarity.

Or just download the SnappingScroll_tutorial_step_4_corrected

Step 5

We want our Layer to be draggable and we did that in the last 4 steps of the tutorial. Now we want the animation to kick in the moment we release the mouse button. To do that, we will create a Classic Animation patch and a Switch patch to trigger the animation. We’ll also add our Mathematical Expression patch to ensure it always goes from 0 to 1, as well as the Transition patch to translate our 0 to 1 animation to whatever Start/End Values we will need later. Connect everything like you see on the image below: Animation_Setup Next, let’s create a Multiplexer to switch between two sources for our Layer X position input. Connect the Interaction2 Drag output to Source Index and SampleOnDrag Value to Source #1. Connect the Transition output to Source #0. Finally, connect the Multiplexer output to Layer X Position.

Now, the Layer X position is set by the Mouse patch while we drag but switches to animation the moment we release the button.

For the Start Value of the Transition patch, we’ll use the SampleOnDrag output, and for the End Value we will temporarily use 0. So, the Layer should slide from the position we left it in to the X value of 0.

We no longer need the SampleOnRelease patch as the Layer position on release will now be adjusted by the animation. Delete the SampleOnRelease patch and connect the Transition output to oldLayerPosition on the Distance patch.

We want the animation to start the moment we release the button, so let’s use our OnRelease output to flip the switch.

Let’s see how things work now: Tutorial Step 5 Wow! It looks like we’re almost done. We left the End Value at 0. That’s why our Layer always animates to X position 0. Let’s think how we can change it so it snaps dynamically to one of our predefined values.

Step 6

In this step, we’re gonna need two points to which we want to snap our Layer (let’s call them Low Edge and High Edge from now on). We need to check whether the Layer was dragged beyond the Threshold point from the Edge point it is currently snapped to. If the answer’s yes, we need to switch the End Value on our animation Transition patch to the other Edge point.

So, let’s create a Mathematical Expression patch and call it Threshold Detector. Open the Settings panel of Patch Inspector and put in the Formula you see below:

currentEdge == lowEdge && currentPosition > lowEdge + threshold || currentEdge == highEdge && currentPosition < highEdge - threshold

There is probably a dozen different ways we could shorten this formula, but this form is the most straightforward and easy to understand.

currentEdge is one of two Edge points (Low or High) that the Layer is currently snapped to (in our case it is the X position of the Layer). We’ll get the currentPosition from our SampleOnDrag patch and we’ll manually set the threshold to the desired value.

The formula will return 1 if one of the following conditions is met:

1) currentEdge equals lowEdge and currentPosition is greater than lowEdge plus threshold

or

2) currentEdge equals highEdge and currentPosition is smaller than highEdge minus threshold

Right-click the patch and publish two input splitters for low and high edges.

Create the Multiplexer patch, call it Current Edge and connect the low/high splitters to Source #0 and Source #1. Create a Switch patch and connect its output to Source Index in Multiplexer. Connect the output of Current Edge to our Threshold condition and to End Value of the Transition patch.

Create a Logic patch and set the Operation parameter to AND mode. Then connect the OnRelease mouse action to one operand and Threshold Detector Result to the other. The Logic patch output will trigger the Switch. This approach is necessary because our detector condition is evaluated constantly and we don’t want it to take effect until we release the mouse button. Threshold_Detector So what happens now is Detector constantly checks whether we dragged our Layer away from the current edge by a number of pixels greater than the Threshold value and returns 1 if we did. However, it only starts working after we release the mouse button. In that split second, the Logic patch returns 1 and the edges are switched.

Cool! The last thing we need to do is to set values for Low Edge, High Edge, and Threshold. In my example it’s 0,320 for the former two and 100 for Threshold. Tutorial Step 6 Brilliant! That’s it! We have a working Snapping Scroll.

Step 7

One last thing you can do is put the composition above in a Macro patch and publish the inputs you’d like to be able to set externally. Here’s the final Step 7 file for you to download.

Chaining animations is easy
Welcome to the Age of Fully Realistic App Prototypes