Code Less & Achieve More with Arrays in Framer

David Lee
Framer
Published in
11 min readMar 8, 2016
Most of app pages contain arrays

I’ve made lots of prototypes with Framer. Some of the prototypes were to show micro-interactions, some of them were to communicate key flows with stakeholders so that all can imagine the same thing. Some of them were to get on a programmer’s good side and to nudge him/her to make it nicely in order to increase the quality of an app. I’ve even made varies versions of prototypes to get feedbacks and insights from users by doing some quick guerrilla tests.

Prototypes are versatile but only they are meaningful when made fast (or within a reasonable timeframe) because they are prototypes, not products. So it is crucial to write compact and manageable code. That’s why I decided to write about the today’s hero, Array.

Without knowing Array, an ordered list, Framer is less efficient. Knowing array will be a powerful tool for you to write more efficient, clean, understandable and manageable code. Of course you’ll save time as a huge bonus.

Why Array?

If you see the app above, every event works the same. If you click on the picture, a sub page slides in and the background moves a little. If you click on the back arrow button on the sub page, it works reversed. Every event behaves in the same way.

The same goes for this app. Every task works in the same way. If you swipe right then its background turns into green and drops to the bottom of the list. It’s deleted when swiped left. All animations are the same as well.

Compact

In my first article, I shared this prototype(Inbox 1–2) and it was somewhat inefficient (although it does what it has to do). You had to make states and add events for all 15 layers individually. Imagine that you have 100 layers.

Yep. That’s why I also shared this prototype(Inbox 1–3). I showed how to simplify code by using array. The total line of code was shortened from 119 to 73. You can make your code more condensed by using array.

Manageable

Wait.. Are 73 lines significantly meaningful comparing to 119 lines? Well, it’s not only about how much less code you wrote. Less code often means that it’s more manageable. If you post something on Facebook, the existing articles are pushed back to give a space for the new post. You can achieve this by changing y values of all existing posts. If the posts are in an array, you can do it in just 2–3 lines. Otherwise you have to manually update positions of all posts. It’s a nightmare.

How to Use Array?

In this tutorial, we are going to make Inbox and Instagram prototypes. Before we get into that, let’s make a simple array first.

Create

An array can be defined by using opening and closing brackets([]).

arr = []

An array can contain any objects like numbers, text strings and other arrays. Items in an array are separated by comma(,).

arr1 = [100, 200, 300]
arr2 = ["hello", "framer"]
arr3 = [arr1, arr2]

Change

An array is an ordered list of objects. Each object is automatically assigned its own index number starting from 0(zero). You can access to an object in an array by putting its index number between brackets. (ie. arr1[0])

print arr1[0]   # result: 100
print arr1[1] # result: 200
print arr1[2] # result: 300
print arr1 # result: 100, 200, 300

Then you can simply assign a new value. See how the value of the first object in the arr1 has been changed.

arr1[0] = 150
print arr1 # result: 150, 200, 300

Add

If you want to add more objects after the creation of an array, you can use .push. It allows you to add a new object at the end of an array and the total number of objects (.length) is increased.

arr1.push(400)
arr1[3] = 400 # override value in this case
print arr1.length # result: 4

Once you’re familiar with array, you will find yourself a lot putting layers in an array. Adding a layer to an array is simple as below.

layer = new Layer
arr.push(layer)

Get (and Remove)

If you want to get a value or remove an object from an array, you can use .pop(). It allows you to cut the last object in an array and paste/assign its value to the left side variable.

val = arr1.pop()
print val # result: 400
print arr1 # result: 150, 200, 300
print arr1.length # result: 3

Copy

Another very interesting thing and you should be careful about object (anything except for number, boolean(true/false) and string text) is that even though you assign it to another variable and change the value, it will affect to the original object. See the example below.

newArr = arr2
print newArr # result: "hello", "framer"
newArr[0] = "bye"
print newArr # result: "bye", "framer"
print arr2 # result: "bye", "framer"

So when you want to make a brand new and decoupled copy of an array, you should write like below. Now whatever changes you make for newArr, it’s irrelevant to arr2.

newArr = arr2[..]

One note here is that you should think of object and visual object(layer) as two separate things. Although you remove(.pop() or whatever means) an object in an array which you think it’s a layer, the layer will still be visible. You need to .destroy() the layer as well.

Array’s Best Friend — For Loop

An array becomes more powerful when used with for loop. Because for loop also saves our life from laborious repetitive works.

For Loop Basic

Here’s how to create many layers at once and put them into an array.

layers = []
for i in [0..9]
layer = new Layer
layers.push(layer)
# The two lines above are the same as layer = layers[i] = new Layer

The code above can be translated in human language like this.

create an array called layers
for index(i) is being increased from 0 to 9 by 1
create a new layer called layer
add layer to layers

Range

We wrote [0..9] in order to loop the indented statements 10 times. It’s the same as [0…10] where with three dots, the range excludes the end number(10). Also, you don’t always need to start from zero (which is most common though). You can pick any number to start and end. See the example below. What do you think the result will be? Well, I’ll not steal your juicy part.

for i in [9..0]
print i

As we discussed above, the number of objects in an array can vary. You can either add or remove objects from an array. Then you need to change the end number of the for loop accordingly. But if you use .length, you don’t need to worry about the range.

for i in [0...layers.length]
layers[i].opacity = 0.5

There is more simple and common way. This enhanced for loop below loops through all layers. Note that you can give any other name than layer. For instance, you can say hi like below. The variable hi only lives within the for loop.

for layer in layers
layer.opacity = 0.5
# for hi in layers
# hi.opacity = 0.5

Sometimes you also need index(i) value. It’s very common to use index together and I’ll cover this with Inbox example.

for layer, i in layers
layer.opacity = i / layers.length # result: 0.0 to 0.9

Array from Sketch Objects

The even more simple way is here. You can make an array with Sketch objects(folders) in only one line like below. It pulls all the children objects inside the Sketch folder called someLayer and put them into childrenLayers in order. I’ll show you the actual application with the Inbox example.

childrenLayers = sketch.someLayer.children

What if you just want to call the first object among 10? What if you want to call the first 5 only? You can use range.

childrenLayers2 = sketch.someLayer.children[0]
childrenLayers3 = sketch.someLayer.children[0...5]

That’s it! You’ve learned the basics of array. Now let’s roll our sleeves and get into the actual prototypes!

Inbox

Please first download the skeleton code below. I wrote a basic structure for you so that you can quickly jump into the juicy part. Please take a look at .sketch file as well because I re-organized some layers from the last one to be more efficient in working with array.

Inbox 2 skeleton code

If you see the prototype above, each circular button is animated with a slight delay (staggered) when the red FAB (Floating Action Button) is clicked. We’re going to make this. I’ll explain this in terms of layer, state and event.

Layers and Arrays

You need to first create arrays. inbox.options.children calls the all the children objects of options (option1, option2, …) in the Sketch file and assigns them to the left variable, options in order. (refer to the image below)

options = inbox.options.children
faces = []
originalYs = []

Now let’s fill in the arrays we made. Under each option object, there are name and face. The children layers can be called using .children. Since face is the second object from the bottom inside option (refer to the image below), we can say option.children[1]. If we have to call name, we can say option.children[0].

The originalYs array stores each option’s original y position. We need this array when we restore the original positions of options. We set each option’s opacity to zero because it shouldn’t be visible until the FAB is clicked.

for option in options
faces.push(option.children[1])
originalYs.push(option.y += optionOffsetY)
option.opacity = 0

There are a number of other ways to make the faces array. If we didn’t use the for loop, we should have done some brainless typings. I don’t recommend this way unless it’s inevitable.

faces = [inbox.face1, inbox.face2, inbox.face3, inbox.face4, inbox.face5]

There’s another way like below. This might be a good alternative, but less manageable. If you change a folder name in Sketch, it will break.

faces = []
for i in [1..5]
face = inbox["face#{i}"]
faces.push(face)

This might be hard to understand but the one line code below works the same.

faces = (option.children[1] for option in options)

States

With array and for loop, you can apply states to all layers in an array at once. Since we’re going to change the scale from 0 to 1, we can write like below.

for face in faces
face.scale = 0
face.states.add
on: { scale: 1 }

You can apply states to overlay, labelCompose, iconPlus and iconWrite respectively with desired properties.

inbox.overlay.states.add
on: { opacity: 1 }
...

Events

We are going to make two events for FAB and overlay objects. The FAB event is for animating faces and labels to appear and the overlay event is to reverse. Let’s make the FAB event first.

inbox.fab.onClick ->
for option, i in options
option.animate
properties:
y: option.y - optionOffsetY
opacity: 1
delay: 0.04 * i

Each option containing face and name moves up as much as optionOffsetY and fades in. Each animation is fired with a slight delay. The i value is increased in each loop which causes to extend the total delay time. You can see the time changes by printing “delay: ” + 0.04 * i.

You can do the same for faces.

for face, i in faces
face.animate
properties:
scale: 1
delay: 0.04 * i

For the rest objects, you can change their states to on.

inbox.overlay.states.switch("on")   # do the same with labelCompose, iconPlus and iconWrite

The FAB event is now done! You can do the same for the overlay event. When the grey overlay is clicked, everything goes to the original state. So you restore all changed states to default.

inbox.overlay.onClick ->
for option, i in options
option.y = originalYs[i]
option.opacity = 0

One thing you need to pay attention to is that you can’t just say ‘option.y -= optionOffsetY’ instead of ‘option.y = originalYs[i]’. Because when you tap the button fast more than twice, it will be misaligned. That’s why we use the array to store the original y values.

That’s it! Compare yours with this Completed Prototype (Inbox 2–1).
I also simplified it further by using functions. (Inbox2–2)

Instagram

The combination of array and for loop is also useful when you make a 2 dimensional grid. there’s a 3 by 3 picture grid in the Instagram prototype below. How can we make this?

Instagram 1–1

To make the 2 dimensional grid, we can use for loop twice. (alias: double for loop) It’s difficult to catch at once but you can get a little understanding of how it works by printing column and row values. It loops 9 (3×3) times total.

for column in [0...3]
for row in [0...3]
print "column: " + column+ ", row: " + row
# create a layer
# add to an array

The statements inside the row for loop are executed 3 times when column is 0. It goes for the same as column is increased by 1. We can make a grid by multiplying row to x value and column to y value of the newly made layer.

I guess you can understand the other parts. If you want to see an even more concise code, please refer to this prototype(Instagram 1–2). I removed unnecessary repetitions and simplified by using functions (which I’ll cover for the next article). I also added swipe gestures.

Good Examples to Try Out

If you want to study further with array, you can dig more into the awesome examples below.

Photo Feed by Jay Stakelon (I also strongly recommend his video tutorial.)

Arrays & For Loops Basics by Marc Krenn (heavily annotated for beginners)

Scroll and Click by Benjamin den Boer

Mobile Navigation by Giel

Load and Display by Benjamin den Boer

Clear App by myself and advanced version by Jiwoong Lee

Still thirsty? Join in the super active Framer FB group, post your work and ask questions!

Thank You

This article is a successor to New to Framer? Just 3 Things to Get You Started, a beginner’s coffeescript and Framer tutorial. Over 700 people recommended the article and encouraged me to write this. If you enjoyed this, please hit the recommendation(♥) button :) It would mean a lot.

Thanks to Marc Krenn and Koen Bok for their early feedbacks.

--

--