The Science Behind Snapping Scroll – Part I: Dragging

In my last article I covered the basics of the QC coordinates system and explained how to convert the Mouse patch output to match the Origami Phone screen.

I also attached my Snapping Scroll file, as an example of practical usage. Now let me delve into the science behind the Snapping Scroll itself.

If you want to follow along, go on and download the SnappingScroll tutorial file.

Snapping Scroll tutorial – Part 1 of 2:

Step 1

In our very first step we’ll connect the ViewerToScreen X output to Layer X Position. SnappingScroll  tutorial. Step 1. Composer screenshotJust as expected, the Layer follows the X Position of the mouse pointer. Actually, it’s the center point of the Layer that follows the mouse. That’s because The Anchor Point of the Layer patch is set to “Center” (and you should leave it there, as it’s not working well on other settings). step_1_snappingScroll Great! The next thing we want to do is to make the Layer follow your mouse pointer only when you press the mouse button.

Step 2

We’ll use the Sample&Hold patch to do just that. The way this patch works is pretty simple. It will pass whatever you put in to the output, but only as long as the Sampling parameter is set to 1. Once it’s set back to 0 the patch will output the last registered value.

That’s exactly what we want. As long as we’re pressing the mouse button the Layer will follow the mouse pointer. Once we release the button it will stay at the position we left it in. SnappingScroll  tutorial. Step 2. Composer screenshot Create the Sample&Hold patch and name it SampleOnDrag. Pass the ViewerToScreen value through that patch and connect the Interaction2 Drag output as Sampling input.

Cool! It works as expected. The problem now is that every time we press the button, the center point of the Layer snaps to the mouse pointer. step_2_snappingScroll And we don’t want that. We don’t really want it to blindly follow the pointer position. In fact, we just want the Layer to move in the same direction and over the same distance as the mouse pointer from the moment we press the button to the moment we release it. Yes! Direction and distance. Nothing else. And because mathematics takes care of the direction for us, all that matters to us is the distance.

Step 3

In our case, the formula for distance looks like this:

New Layer Position = Current Mouse Position – Mouse Position onPress

So… we need to know the point at which we pressed the mouse. To do that we’re gonna use another Sample&Hold patch (name it SampleOnPress), only this time we want it to sample the mouse position for just a split second, at the precise moment we started dragging. SnappingScroll  tutorial. Step 3. Composer screenshot So instead of directly connecting the Interaction2 Drag output to the Sampling input we will pass it through Pulse patch (It will convert any continuous signal into a single pulse).

Now we have the position at which we started dragging.

From then onwards, if we subtract it from the mouse position, we will get the absolute distance the mouse traveled from the moment we pressed the button.

Create the Mathematical Expression patch (name it Distance), open the Patch Inspector, select Settings and enter our formula:

currentMousePosition - mousePositionOnPress

It will automatically create two inputs in our Distance patch. We take currentMousePosition from our ViewerToScreen patch and mousePositionOnPress is obviously our SampleOnPress value. Connect the output from our Distance patch to SampleOnDrag.

Great! Now we can drag the Layer from any point. It no longer snaps to center. step_3_snappingScroll However! Now it will always start from X = 0 because when we press the button, currentMousePosition and mousePositionOnPress are the same. If we subtract one from the other we’ll get 0.

Step 4

We need another variable – Old Layer Position. To calculate the new Layer position we have to add the old position to the current distance traveled by the mouse.

Now the formula should look like this:

New Object Position = Old Object Position + Current Mouse Position – Mouse Position onPress

So, go on and update the Mathematical Expression patch:

oldLayerPosition + currentMousePosition - mousePositionOnPress

How do we get the old position? Create another Sample&Hold patch (name it SampleOnRelease), only now take the output from SampleOnDrag we created in Step 2 and connect it to the Value input in the newly created Sample&Hold patch. For Sampling we will use the Click output from the Interaction2 patch. Why Click? Well, we want to sample the current object position at the moment we release the mouse button. Click will return 1 at this exact moment 1. SnappingScroll  tutorial. Step 4. Composer screenshot The last thing we have to do is connect the Output from SampleOnRelease patch to our Distance patch.

Great!! Now dragging works perfectly. step_4_snappingScroll Let’s take a break here. Stay tuned for the 2nd (and final) part. We’ll create snapping animations and control their Start and End values dynamically.


  1. Long after we published this post, I noticed that Click won’t return 1 if you release the mouse button outside of the Layer bounds. It would be safer to use Drag with Pulse patch and Detection Mode set to Trailing Edge.

Welcome to the Age of Fully Realistic App Prototypes
Quartz Composer. Origami. Mouse. Headaches.