Framer practice: Looping Carousel 2

Unlock more of the pageComponent’s functionalities with loops and arrays.

Sophie Rahier
8 min readJul 26, 2018

This is part 2 of 2, and covers using loops and arrays to create a looping carousel. To read up on the first steps of the process, including pageComponent basics, follow this link.

Let’s take on the second version of this looping carousel! While the first method works well for small scale projects, this variant is optimal when working with more data! I’ve added a couple design elements to my previous example to showcase more of this method’s potential.

Here’s what this version will look like:

Carousel version 13/10.

View on desktop or open in Framer

So here’s the design-only file if you’re tagging along for the ride!

A more efficient design mode

The changes in design mode essentially getting rid of all the cards, and replacing them with a template-like one instead. It makes it look pretty clean.

Let’s have a closer look at this new card:

I’ve renamed it card00, and I now have 3 layers inside it: graphic (I didn’t want to get mixed up with the word image, bear with), title and author. Notice neither of these three layers are targeted.

Keep the set-up the same

The carousel set-up is the same as the previous one (covered here) —

  • The desktop settings stay the same
  • The scroll component stays the same
  • The page component stays the same
  • The headline position also stays the same

The data array

Before we start generating cards, we need a place to put the data that’ll go in there. That’s where the array comes in! An array is basically a big list, similar to JSON format. Each list item has a position in the list. This translates to a number, also known as the item’s index. The first item in an array will always have an index of 0, the second an index of 1, the third an index of 2… and so on.

Arrays can also contain lists within them. In our example, the array I put together is made up of a list per card. Each list contains the data for title, author, and image.

Let’s have a look:

content = [ 
cards : [
{ title: “Curious collie”,
author: “Baptist Standaert”,
image: “images/dog1.jpeg”}
{ title: “Pug on sofa”,
author: “sarandy westfall”,
image: “images/dog2.jpeg”}

{ title: “Beagle in a bag”,
author: “Savs”,
image: “images/dog3.jpeg”}

{ title: “Cool Chow”,
author: “alan King”,
image: “images/dog4.jpeg”}

{ title: “Dog duo”,
author: “Jay Wennington”,
image: “images/dog5.jpeg”}

{ title: “Hanging there”,
author: “Erda Estremera”,
image: “images/dog6.jpeg”}
]
]

Curly and square brackets aren’t fun to use or easy to remember but they’re essential to tell Framer how the lists fit together. Also, notice that I’ve kept my data in order; this will be important when we create our card copies later.

Now we have our content, let’s look into generating those cards…

Generating the cards using a loop

First things first, let’s tell Framer we want the cards to be based on our card00, so we’ll initially use the loop to create copies. We’ll then use it to re-name them.

We have 6 dog cards, so let’s make it run 6 times:

for i in [0…6]
card = card00.copy()
card.name = “card” + (i + 1)

It took me way too long to wrap my head around loops; I now try to think of them as a multiplier. The i is just a letter that, when used under the loop, means “whatever item’s index”. This means that first line could be translated to:

“For each item in a position between 0 and 6, make the following happen:”

Here, we’re creating a copy of. Our card00, which will be called card. Then we’re assigning those copies a name which combines the word “card” and their index +1. I add the +1 so that we don’t have a card0, but that’s optional.

Naming the cards makes it easier to see what’s happening and thus debug when needed. It’ll also be key when calling on specific ones.

Let’s also go ahead and add these cards to our page component so we can see what’s going on.

for i in [0…6]
card = card00.copy()
card.name = “card” + (i + 1)

page.addPage(card)

You should have a sexy slideshow of 6 grey cards.

And now, putting the data into the equation! We need to fit that code under the loop as well, as we want it to happen for all the cards generated by the loop.

Pulling data from our array

Let’s start by the title:

  • You’ll first want to use selectChild to select the text layer that we left un-targeted in design mode. You could go and target it, but this is a useful way to do it when switching back and forth between multiple designs, as you won’t have to go and re-target every single sub-layer each time you switch.
  • Then work on changing the title’s text to the “title” value found in our content array, in the right card list.

I’m not sure if having it typed out made it less confusing; so here’s the code I’m talking about:

for i in [0…6]
card = card00.copy()
card.name = “card” + (i + 1)
card.selectChild(“title”).text = content[0].cards[i].title

page.addPage(card)

If you wanted to go and target you card’s content, your code would look like this:

for i in [0…6]
card = card00.copy()
card.name = “card” + (i + 1)
title.text = content[0].cards[i].title

page.addPage(card)

If you look at the way we’re calling the data, it’s simply referring to the name of the array and its index: content[0] is the only item at its level, so its index is 0. Within content[0], we want Framer to fetch the data relevant to each card generated, so we use card[i] to make sure it looks into a different list per each card. Finally, we specify what item to look for in each list, in this case: title.

We can repeat this code for the cards’ authors and images.

for i in [0…6]
card = card00.copy()
card.name = “card” + (i + 1)
card.selectChild(“title”).text = content[0].cards[i].title
card.selectChild(“author”).text = “Photo by “ + content[0].cards[i].author
card.selectChild(“graphic”).image = content[0].cards[i].image
page.addPage(card)

Ta-da! The data now shows up in our pageComponent!

Creating the loop

The concept is the same as in the previous carousel: We’ll add a copy of the first page at the end, a copy of the last page at the start, and make the carousel snap to the real pages when it lands of copies. If we make this transition happen with no animation, it’ll looks like it’s looping around.

However, because we’re now using a loop to generate cards, there are two things that change:

  1. How we create copies of the first and last pages
  2. How we call the cards when telling the page component to snapToPage

Creating copies using the data array

In this case, instead of using the copy() function, we’ll simply copy the right data within our array. This is why the order in which we introduce the data is important!

Practically, this means we’ll copy the data for the first card, and add it to the end of the array, and vice-versa for the last card. So, copy the "Border Collie" data and paste it to the very end of the array, then copy the "Hanging There" data and paste it at the very start.

If I were to “wireframe” our updated data array, it would look like this:

With this new array, we now 8 eight sets of data, or 8 cards. Make sure you edit your loop to generate 8 cards rather than the previous 6.

Also notice the “fake” cards are now automatically named card1 and card8 because of their index.

Snapping to different pages

Before we start playing around with the first and last page, make sure we’ve kept this line of code in: page.snapToPage("right", false), to tell our page component to start on the second page from the right, ie. the our first “real” card.

Let’s go ahead and reuse the onAnimationEnd event we used in the previous iteration of this carousel, and adjust the card name to card8:

page.content.onAnimationEnd ->
if page.currentPage.name is “card8”
page.snapToPage(card1, false)

This won’t work because card1 within the brackets refers to an object rather than to the name of an object. In this case, card1 is just a name we generated and assigned to a copy() earlier, under the loop we created. To use this exact syntax we’d need to refer to an actual object, or it won’t work.

Which means we need another way of talking to the object we’ve named card1; we can use the object’s index and do this:

page.content.onAnimationEnd ->
if page.currentPage.name is “card8”
page.snapToPage page.content.children[1]

This syntax calls on specific children of the page component’s content (ie, the pages we generated to happen inside the page component). The [1] refers to the index of the page we want to animate to. In this case, it’s 1, as the fake card has index 0.

This bit of code also has an option to turn animation on or off with a boolean, which gives us this:

page.content.onAnimationEnd ->
if page.currentPage.name is “card8”
page.snapToPage page.content.children[1], no

Let’s re-use this code for the last card;

page.content.onAnimationEnd ->
if page.currentPage.name is “card8”
page.snapToPage page.content.children[1], no
page.content.onAnimationEnd ->
if page.currentPage.name is “card1”
page.snapToPage page.content.children[6], no

Here, the card we want to animate to is “card7” which comes 7th in the array, and therefore has an index of 6 because of the 0 start.

And, ta-da! That’s a looping carousel!

That’s all folks!

Let me know what you thought of this tutorial, if you found it helpful, and of course drop any questions in there as well, as I’ll do my best to answer them!

I’m also always happy to write up an extra example, and if you happen to use or remix this in one of your prototypes, I’d love to see it!

Find me on my very active Twitter: @a_soapy

✌️🌞

--

--

Sophie Rahier

Product designer at Planes, otherwise mostly outdoors. I love cycling, prototyping, and wonky pottery.