Prototyping with the motion sensor using Framer.js

Create impressive parallax effects in your prototypes using the motion sensor and a few lines of code.


Framer is a fantastic prototyping framework that makes it easy to test out cool interaction ideas for mobile and desktop. Among other things, you can prototype swipe and drag gestures with Framer, or use it to add motion to your web apps.

Since Framer uses Javascript, it’s very easy to make use of the different sensors in your phone, such as the GPS or the motion sensor.


Before we begin, you can test this on your phone at http://cem.re/framer-parallax and find all the code in CodePen. (I also included code that simulates the motion sensor with your phone ☺)


Basic use of the motion sensor is incredibly easy. If you’re on a device that has a gyroscope and use a browser that supports motion events, you can listen to the DeviceMotion event which is fired periodically as the motion sensor detects movement.

This event has a couple properties that you can see here, we’re the most interested in the accelerationIncludingGravity property which gives us the rotation of the device in three different dimensions.

accX = 0;
accY = 0;
window.addEventListener("devicemotion", function(event) {
accX = event.accelerationIncludingGravity.x;
accY = event.accelerationIncludingGravity.y * -1;
});

These values are close to 0 when your phone is upright and straight, and move into the positive and negative the more you tilt it.

To demonstrate the effect, I made a janky simulation of a phone in the browser. Here you can see the phone rotating around its axes:

It’s not hard to imagine how we could use these accelerometer values in Framer. Let’s have a view whose middle sits at 60, 60 and moves slightly based on accelerometer values.

View.midX = 60 + accX * 3;
View.midY = 60 + accY * 3;

Here the number 3 is a factor we use to amplify the data coming from the sensor. Reduce it to make the effect more subtle, increase it to make it more dramatic.

By moving the red square based on the motion sensor, we create the illusion that it’s hovering over the phone.

Let’s take it a step further by adding a back layer and animating it as well. To make the example more realistic, I will use a blurred photo (Background), and some chat bubbles (Content) over it. (To see how they are defined, check the CodePen)

Background.x = accX * 3;
Background.y = accY * 3;
Content.x = accX * 3;
Content.y = accY * 3;

This isn’t quite the same effect as the one on the iOS home screen, though. You may notice two things: the background is moving in the same direction as the bubbles, and there are black gaps around it when it’s tilted.

For a more realistic effect, we need to make two changes. First, the background should move in the opposite direction of the image. Second, to avoid the black gaps, we should make the background view bigger than the screen, so even when it’s moved, it will fill the screen.

Background.width = 720;
Background.height = 1216;
Background.x = accX * -3 — 40;
Background.y = accY * -3 — 40;

We subtract 40 from each dimension so that we end up with an extra 80px around our axes.

Looks good! However, when you try this out on your phone, you may notice that the effect isn’t very smooth. This is because real time values coming from the motion sensor are quite noisy and very sensitive even to the slight shaking motion of your hand, as you hold the phone.

Luckily there is a very easy way to smooth these sensor values. Every time a motion is detected, instead of directly applying it, we’ll average out the detected values with the previous value. (“Averaging out” is technically not correct but will gives you an idea of what’s going on).

accXsmooth = 0;
accYsmooth = 0;
factor = 0.4;
window.addEventListener("devicemotion", function(event) {
accX = event.accelerationIncludingGravity.x;
accY = event.accelerationIncludingGravity.y * -1;
accXsmooth = factor * accXsmooth + (1 - factor) * accX;
accYsmooth = factor * accYsmooth + (1 - factor) * accY;
 Content.x = accX * 3;
Content.y = accY * 3;
Background.x = accXsmooth * -3 — 40;
Background.y = accYsmooth * -3 — 40;
});

You can use values between 0 and 1 for the factor (not including 0 and 1 though). The bigger the number, the smoother the motion, and the slower your phone will respond to the tilt.


This is it! With a couple lines of code, you can make your prototypes react to motion in realistic ways. If you haven’t been writing code as you read along, now would be a good time to look at the CodePen to examine the code.


What else do you want to make with Framer? Tweet at me (@gem_ray) and suggest the next blog post!

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.