N° 22— Yelp’s  

https://framer.cloud/cYPLH

Design

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 in Yelp, which is a cute, little critter that boards a rocket and blasts off. Seemed like a great to play with in .

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.

Code

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
mainContent.draggable.constraints =
y: navbar.height
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, 
x: 155
options:
time: 0.05
rocketRumbleRight = new Animation rocket,
x: 156
options:
time: 0.05
exhaustRumbleRight = new Animation exhaust,
x: 169
options:
time: 0.05
exhaustRumbleLeft = new Animation exhaust,
x: 167
options:
time: 0.05

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
ground.animate
y: 370
options:
time: motionTime
tower.animate
y: 304
options:
time: motionTime
fire.opacity = 1
clouds.animate
y: 280
options:
time: motionTime
curve: Bezier.easeIn
sun.animate
y: 153
options:
time: motionTime
rocket.animate
y: 135
options:
time: motionTime
insideRocket.animate
y: 165
options:
time: motionTime
critter.animate
y: 165
options:
time: motionTime
fire.animate
y: 198
options:
time: motionTime

And here is my reset function, which animates the main content back into position, and then resets the scene after a short delay:

resetScene = ->
mainContent.animate
y: 130
Utils.delay 0.4, ->
critter.y = 128
ground.y = 155
tower.y = 144
tower.opacity = 0
rocket.y = 6
insideRocket.y =41
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 
rocketRumbleLeft.start()
rocketRumbleLeft.onAnimationEnd ->
rocketRumbleRight.start()
rocketRumbleRight.onAnimationEnd ->
rocketRumbleLeft.start()
exhaust.visible = true
exhaust.opacity = 1
exhaustRumbleRight.start()
exhaustRumbleRight.onAnimationEnd ->
exhaustRumbleLeft.start()
exhaustRumbleLeft.onAnimationEnd ->
exhaustRumbleRight.start()
else
rocketRumbleLeft.stop()
rocketRumbleRight.stop()
exhaustRumbleLeft.stop()
exhaustRumbleRight.stop()
exhaust.opacity = 0

Lastly, when the dragging ends, I check to see if the rocket should launch:

mainContent.onDragEnd ->
if mainContent.y > 240
exhaust.visible = false
flyingAnimation()
Utils.delay 1.8, ->
resetScene()
rocketRumbleLeft.reset()
rocketRumbleRight.reset()
else
resetScene()
rocketRumbleLeft.reset()
rocketRumbleLeft.reset()

Lesson Learned

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
https://framer.cloud/cYPLH



Source link https://blog.prototypr.io/using-framer-to--the-refresh-rocket-interaction-and-animation-e33ffcbf1cb2?source=rss—-eb297ea1161a—4

LEAVE A REPLY

Please enter your comment!
Please enter your name here