Framer Cheat Sheets: Utils.modulate

Utils.modulate allows the user to interact and create incremental changes in your prototype. This Cheat Sheet is for intermediate Frameristas, but I encourage beginners to give it a try, too!

Tess Gadd
Designing Humans
7 min readAug 31, 2017

--

Hold onto your keyboards ladies and gentlemen, it is time to graduate onto a rather tricky utility, namely Utils.modulate. In some of my previous Cheat Sheets, I have glossed over it in the examples at the bottom, but today we will go into it in more detail.

While it was one of the first things I learnt, I didn’t really understand it (Copy and pasting tends to leave some knowledge gaps ). So while it can be a bit tricky, I encourage beginners to give it a try too.

Like the other Cheat Sheets in this series, we will look at the very basics: simple properties and commonly used patterns. This was written for people like me — who aren’t great at writing code, but are pretty darn good at copy and pasting. If you don’t have Framer yet, download a free 2 week trial.

In this Framer Cheat sheet, we will look at the following:

  1. What is Utils.modulate?
  2. The anatomy of Utils.modulate
  3. Utils.modulate and …
    a. Page components
    b. Scroll components
    c. Slider components
    d. Input fields
    e. Animation
    f. Drag
    g. MouseTracker
    h. Color.mix
  4. Some common examples
    a) Onboarding tutorial screens
    b) Header changes on scroll
    c) Convertor

1. What is Utils.modulate?

In life, when something happens, it usually affects something else. For example, when I eat chocolate, I get fat. When I drink, I get drunk. When I watch a cat video, I laugh.

It also works incrementally, for example — one slab of chocolate isn’t going to make me fat, but 35 are. One glass of wine does nothing to my sobriety, however, 4 glasses of wine, 3 tequilas and an old fashioned later and my dignity has gone out the window.

Utils.modulate works in much the same way. It deals with two properties, one that is a cause and another that is an effect.

When I eat chocolate — I put on weight (this is very sad, I know). So, the amount of chocolate eaten is the Property that causes change, and weight is the Property that occurs because of that change.

#This is not actual code - demonstrative purposes only.Tess.weight = 60
Tess.chocolateEaten = 0
Tess.whenEatsChocolate ->
Tess.weight = Utils.modulate(Tess.ChocolateEaten, [0 slabs,23 slabs], [60kg, 150kg])
# if I eat 4 chocolate slabs, then i would weigh 75
# if I eat 20 chocolate slabs, then I would weigh 138
# if I eat -2 chocolate slabs, then I would weigh 52

Incase anyone is wondering — I do eat a lot of chocolate.

2. The anatomy of Utils.modulate

As mentioned before, when using Utils.modulate there are usually two elements, a Property that causes change and Property that occurs because of that change.

When Input changes: An event is needed to alter the Output
Output: Property that is effected by change
Input: Property that affects change
Output’s & Input’s range: Theses two ranges correlate. The starting number (in green) correlate, as do the ending numbers (in red).
Limit Setting: Read more about limit settings below

Limit Setting

This is a boolean (true or false statement). By default it is set to false. This relates to the ranges and determines whether you can extend beyond them.
So, if you limit is set to true, then even if the property that causes effect exceeds it’s range, the property that is effected won’t change.

slider1.onValueChange ->
shape.rotation = Utils.modulate(slider1.value, (0,1), (0,360), true)
slider2.onValueChange ->
shape.rotation = Utils.modulate(slider1.value, (0,1), (0,360), false)

PRO TIP: because Utils.modulate is set to false by default, you can save a bit of time by leaving out the false .

shape.rotation = Utils.modulate(slider1.value, (0,1), (0,360), false)#is the same asshape.rotation = Utils.modulate(slider1.value, (0,1), (0,360))

3. Utils.modulate and…

a. Page components

I love dynamic intro tutorials on apps, and if you do too, check out this cool IF onboarding prototype by Tes Mat.

The shape on the right is reacting to the user scrolling through pages. Note how it has a different animation on each page. Also, you MUST use a limit (the true at the end) otherwise the layer will continue to change as you scroll through pages.

PageComp.onMove ->shape.scale = Utils.modulate(PageComp.scrollX, [0, pageW], [1, 0.5], true)

NOTE: It you can confuse Framer when you try to do the same action twice while scrolling through pages (e.g. If you make the layer bigger between pages one and two, then make it smaller between pages four and five). To combat this, use an if statement.

PageComp.onMove ->  shape.scale = Utils.modulate(PageComp.scrollX, [0, pageW], [1, 0.5], true)

if PageComp.scrollX > (pageW * 3)
shape.scale = Utils.modulate(PageComp.scrollX, [(pageW * 3 + 20), (pageW * 4)], [0.5, 1], true)

b. Scroll Components

Utils and scroll can create pretty cool interactions as you go down a page. Fancy parallax scroll, things moving as you go down, etc, can all be done with Utils.modulate .

ScrollComp.onMove ->

shape.rotation = Utils.modulate(ScrollComp.content.y, [0, -1000], [0, 360])

c. Slider Components

If you need a slider to effect change, it is probably best to use the .onValueChange event. You can however also use .knob.onMove or .konb.onDrag too.

slideComp.onValueChange ->   shape.rotation = Utils.modulate(slideComp.value, [0,1], [0,360])

d. Input fields

Input fields that can change something incrementally are useful for currency and measurement conversions.

I suggest using Jordan Dobson’s prototype and module for making an input field (Cheat sheet coming out soon). Make the event happen on .Input, (value, layer).

celcius.on Events.Input, (value, layer) ->

fahrenheit.html = Math.round(Utils.modulate(celcius.value, [-40, 1832], [-40, 1000]))

SIDE NOTE: If you try to make two input fields effect each other (example) — it works, but gives you this error: RangeError: Maximum call stack size exceeded. Basically — you are creating an infinite loop that kind of breaks everything. If anyones knows a work around, let a girl know!

e. Animation

In the below animation, as the circle’s x value changes, so does the rotation of the square. You will need to trigger the animation for the square to rotate.

Circle.onClick ->  Circle.animate
properties:
x: 300
Circle.on "change:x", -> shape.rotation = Utils.modulate(Circle.x, [20, 380], [0, 360])

f. Drag

In this example, the shape on the right alters border radius and rotation depending on the location of the square.

Square.onMove ->

shape.borderRadius = Utils.modulate(Square.y, [0, 150], [0, 200])
shape.rotation = Utils.modulate(Square.x, [0, 420], [0, 360])

g. MouseTracker

This is a fun interaction — that as far as I am concerned, never gets old (Look how cute this prototype by Junhyuk Jangn is!).

To get the shape to move vertically and horizontally, you have to modulate both the x and y values.

bg1.onTouchMove (event) ->

shape.x = Utils.modulate(event.offsetX, [0, bg1.width], [0, bg2.width] )
shape.y = Utils.modulate(event.offsetY, [0, bg1.height], [0, bg2.height] )

h. Color.mix

This is just a fun experiment with Color.mix.

Color.mix allows you to mix two colours together at a specific proportion. For example: Color.mix("red", "blue", 0.5) will give you purple, where as Color.mix("red", "blue", 0.9) will give you a slightly purply blue.

So to get the colour to change incrementally according to the slider, we replace the Color.mix‘s mixing value with Utils.modulate(... .

slideComp.onValueChange ->

shape.backgroundColor = Color.mix("53E2C3", "A85DD7", Utils.modulate(slideComp.value, [0,1], [0,1]) )

Some common examples

These are just some common examples of places that I have used Utils.modulate in the real world.

1. Onboarding tutorial screens

I am a sucker for pretty onboarding / tutorial screens. This is a place were you can focus on making something really pretty without worrying too much about the usability (Moohahaha!).

Using Utils.modulate you can make smooth animated transitions between each page.

https://framer.cloud/xMENp (the link says xMen, lol)

2. Header changes on scroll

This adds a little bit of flair to any scrolling experience. While it might not always be practical, it is pretty.

https://framer.cloud/Qqfbg

3. Convertor

Convertors help you change measurements, currency, temperature and more. While convertors are out of fashion (Google has got that covered), they are fun to make. Please bare in mind that you will need an input module (see above or just get the file below).

https://framer.cloud/wEVnG

Look how clever we are! Hopefully this cheat sheet helped you, and if it didn’t or you want to learn more about something else, please leave me comment, and I will update :)

--

--