Animations challenges #3 — Zenly Pops iOS Animation

Aymen Rebouh
Eureka Engineering
Published in
7 min readDec 3, 2020

--

Animations challenges is actually pretty fun. It’s about picking a random animation in one of the app that we use everyday ( twitter, Facebook, Slack, others .. ) and try to recreate it together by doing Pair Programming.

December 12 was the first day for me or John, both iOS Engineer at Eureka, for our Animations Challenges.

Animations are very funny. When you look at them, they look very simple, but when you try to look closer, you will notice that it involves many changes/sub-animations under the hood, making the end result amazing and almost unnoticed.

So the goal of those animations challenges is to try to analyze those animations and try to replicate them. After that, there will be a blog article showing how we approached this challenge.

For this animation, I had to work on it by myself for the Advent Calendar event. John will join us for another challenge, hopefully!

This post is a part of the Advent calendar organized of Eureka, following the second day article written by Shima in Japanese regarding the implementation of the tooltip on iOS.

Introduction

The third animation I decided to reproduce was the animation from the Zenly Pops animation.

https://community.zen.ly/hc/en-us/articles/360005119977-Pops-

Let’s dive in

Initial state:

I created a quick design to start from. It has a label, background, and a white view.

Observation #1: Faces are falling from the sky!

Faces are falling from the sky

One of the first observation we can make is that we can see faces falling from top to the bottom.

  • They fall one by one
  • They fall from different x position
  • The way they fall down feels very familiar. It falls faster over time. Similar to taking an orange and letting it fall from a table.

While creating such “falling” animations may be possible using the traditional way to make animation with UIKit and custom curve animations, those animations can easily be made with UIKitDynamics.

UIKitDynamics have a series of classes we can use to communicate to a user how something feels by trying to reproduce real-life physics.

We could divide UIKitDynamics into two:

  • Behavior classes: those classes are specific dynamic behavior such as gravity, collision, etc.
  • UIDynamicAnimator: the class that will allow us to manage our behaviors above.

To reproduce the falling effect, the behavior we will be first using is the UIGravityBehavior: gravity is an invisible force of attractions that exists between two items. Earth’s gravity is what pulls us on the ground and that’s why items are falling down.

  • 1: the class that will allow us to manage our behaviors aka specific dynamic behavior
  • 2: We delay the creation of the face view to display them “one by one”
  • 3: Faces will have a random size
  • 4: x: We position the face randomly in the x-axis, so that faces can fall down from different position, y: negative so that they are falling from above
  • 5: We add a gravity behavior for each of our face
  • 6: We ask our “manager” to add the gravity behavior, which will automatically trigger the animation.

Which produce this result:

Gravity behavior and face falling

Observation #2: Collisions everywhere!

Collisions

We can notice that there are not only one type of collisions, but multiples ones:

  • Between the faces and the bottom white view
  • Between the faces themselves
  • Between the faces and the borders of the screen.

The behavior we will be for creating collision-like effects is by using the UICollisionBehavior.

Similarly to the UIGravityBehavior, we will create an instance of it, add a collision behavior for each of our faces and then tell our animator manager to add it.

If you run the code…

…nothing will happen 😅

The reason is that although we made our faces views to have a collision behavior, we didn’t say anything about the rest: the white bottom view, the left edge or even the right edge. Our faces views are not aware of any “walls” or “barriers”, so we need to communicate that.

One way of doing that is by manually adding an invisible “boundary” that will act as an invisible wall. We do that by calling the addBoundary method from the collision behavior and we indicate the path of our white bottom view.

So since we are using the collisionBehavior property inside a different method, we need to move its declaration from inside the viewDidLoad to outside the viewDidLoad.

And the result is:

The white bottom view is now acting like a wall ✅
But wait.. Why are our faces escaping to the left and the right edges now??

Well, similarly to what we did to our white bottom view, we need to create invisible walls for the left and right edges so that our faces can stay within the area.

Since the edges positions are quite straightforward, we can directly add them in the viewDidLoad:

If we run, the result is:

Well… It’s quite bugged 😅 🙄

My guess is that it’s because we didn’t really set physic-related properties in the code such as the friction between the views. We will see that in the next section.

Observation #4: Polishing physics

Let’s take a look again at the original animation:

  • One thing we can notice is that the faces views don’t have a big elasticity or even not at all. It’s not as bouncy as a ping-pong ball or a basket ball.
  • Another thing we can notice is the friction. Friction is a force that opposes the sliding motion when two object rub each other. When you’re skying, your ski and the snow are in friction. You are still moving fast on top of the snow because the friction is low, which let the motion happens fast. So another observation in this Zenly animation is that it doesn’t look like there is a big friction between the faces views. Face views are almost sliding when they are rubbing into each other.

So let’s try to apply those observations by using a new behavior class, called UIDynamicItemBehavior. This class allows us to customize some real-like physics properties such as elasticity, friction, etc.

And the result is:

It’s better! 🤓

Observation #5: Pan gesture to move items and create chaos!

If you wait till the end of the gif animation, you will notice that items are moving and pushing each other near the end:

Collisions

The way I approached this behavior is by adding a pan gesture that will push the face view toward the direction of the pan!

By applying the pan gesture to the face view with my finger, I will use a dynamic behavior to translate/push the face view following the velocity of the gesture.

To do that,

and the result as we apply pan movements:

✅ Good job for reading and reaching the end 💪

You can now reproduce a “similar” animation as the Zenly Pops animation!

You learned that sometimes, something that looks like a challenge, once putting enough through on it, can be achieved without struggling too much.

This is the third animation challenge blog article I write, and there is going to be more! So if you have any feedbacks, let me know :).

You can find the full animation project there:

If any questions, you can reach me on twitter anytime :).

--

--