Having recently relocated to Dallas, Texas, I’ve been relying heavily on Yelp to find date night dinner options. The other day I noticed the refresh animation in Yelp, which is a cute, little critter that boards a rocket and blasts off. Seemed like a great interaction to play with in Framer.
The image above gives you a good idea of how I used screen shots to build my interface for this prototype. Rather than try to make everything exactly like the original, I just eyeballed most of the layout. I also used more of a wireframe look, which helps put the focus on the interaction and the animation, where it should be.
Most of my design time for this prototype was used to create the nine distinct elements of the rocket animation: the critter, the rocket, the inside of the rocket, the exhaust smoke, the fire from the rocket thruster, the launch tower, the sun, the ground, and the clouds.
After creating the pieces for the refresh animation, it was time to hook them up in code and make the magic happen. First, I set up the draggability of the main content.
mainContent.draggable.enabled = true
mainContent.draggable.horizontal = false
height: mainContent.height + 110
mainContent.draggable.overdrag = true
Next, I set up some initial properties to set the scene.
navbar.x = 0
mainContent.x = 0
mainContent.y = navbar.height
tower.scale = 0.75
fire.opacity = 0
exhaust.visible = false
In Yelp, when the user pulls down to refresh, when the pull down reaches a certain height, and the critter is aboard the rocket, the rocket and the exhaust smoke begin to rumble. So I created a few animations for the rumbling. I made one for moving to the right and another for moving back to the left when the first animation ends, so it would appear to move back and forth.
rocketRumbleLeft = new Animation rocket,
rocketRumbleRight = new Animation rocket,
exhaustRumbleRight = new Animation exhaust,
exhaustRumbleLeft = new Animation exhaust,
Next I created a pair of functions, one for the flying animation and the other for reseting the scene when the animation is done. Here’s the flying animation function (notice that the first thing I did was to create a variable so that I could easily tweak the timing as needed):
flyingAnimation = ->
motionTime = 2
fire.opacity = 1
And here is my reset function, which animates the main content back into position, and then resets the scene after a short delay:
resetScene = ->
Utils.delay 0.4, ->
critter.y = 128
ground.y = 155
tower.y = 144
tower.opacity = 0
rocket.y = 6
clouds.y = -342
fire.opacity = 0
fire.y = 218
I used the Events.Move method as my trigger because I wanted my transitions to be happening regardless of whether I was touching the screen or not. Like, for instance, if I abort the refresh and let go of the screen, allowing the animation elements to just go back to their starting positions.
mainContent.on Events.Move, ->
critter.y = Utils.modulate(mainContent.y, [130, 240], [128, 185], true)
ground.y = Utils.modulate(mainContent.y, [130, 240], [155, 210], true)
tower.y = Utils.modulate(mainContent.y, [180, 240], [144, 128], true)
tower.opacity = Utils.modulate(mainContent.y, [180, 240], [0, 1], true)
rocket.y = Utils.modulate(mainContent.y, [180, 240], [50, 155], true)
insideRocket.y = Utils.modulate(mainContent.y, [180, 240], [70, 185], true)
sun.x = Utils.modulate(mainContent.y, [130, 240], [50, 70], true)
sun.y = Utils.modulate(mainContent.y, [130, 240], [153, 143], true)
Also within that Events.Move function, I included conditionals that checked for the y-position of the main content to see if the pull-down was far enough to start the rumbling rocket.
if mainContent.y > 240 # This should probably not be on drag end
exhaust.visible = true
exhaust.opacity = 1
exhaust.opacity = 0
Lastly, when the dragging ends, I check to see if the rocket should launch:
if mainContent.y > 240
exhaust.visible = false
Utils.delay 1.8, ->
Not worrying about every little detail in the interface was a nice change for me, so I’ll be doing that more.
Also, if you go and check out the prototype for yourself, you will notice that it works well the first time, but gets a little buggy on subsequent attempts. I spent a ton of time trying to debug, and then finally decided that what I had was good enough. I need to be able to make that call sooner so I can avoid wasting time in fruitless dubugging.
See for Yourself
Feel free to download the prototype and poke around in the code a bit (the link is repeated below). And remember, prototyping isn’t about writing clean, elegant code. It’s about doing enough to communicate the intended experience.
Yelp Refresh Rocket