Animating the album cover
When the music is playing the album art should be full-size, just like it is now, and when paused the album cover shrinks (and also loses most of its shadow).
FYI: The shadow in the original app is actually more of a blurred version of the album cover, but since our cover is black we’ll keep it simple and use a shadow.
To animate between these two states we’ll use, of course, States.
But first, we have to set up a few things.
Setup
Later on, we’ll show this same album cover very small on the mini-player… and have the whole “Now Playing” screen disappear. That’s why we should lift the album cover layer out of its parent, and put it directly in the ScrollComponent.
That’s easily done though, with just one line:
$.Album_Cover.parent = scroll_now_playing.content
It’s now still in the ScrollComponent, but independently, as a sibling of the “Now Playing” screen. (And we didn’t even have to correct its position.)
Next, we need to get rid of the existing (static) shadow. I made it a separate group in the Sketch document, so you can just make this $.Album_Cover_shadow
layer invisible.
$.Album_Cover_shadow.visible = no
Creating the “playing” and “paused” states
We can now define the states.
When the music is playing, the album cover should look like this:
- It’s shown at its full 311 x 311 points — so its
scale
is1
- The shadow’s color is 40% black —
”rgba(0,0,0,0.4)”
- The shadow is projected downwards —
shadowY
is20
points - … but also outwards in all directions — a
shadowSpread
of10
points - (There’s no
shadowX
) - The shadow’s blur is also high —
50
points of Gaussian blur
And when the music is paused, it should look like this:
- The album is 249 x 249 — which makes for a
scale
of0.8
- The shadow is very light: only 10% black —
”rgba(0,0,0,0.1)”
- A
shadowY
of19
- No
shadowSpread
- A
shadowBlur
of37
points
(The shadow will actually end up being 20% smaller because of the scale change.)
To keep it simple we’ll call our states ”playing”
and "paused”
. We can define both of them at the same time:
$.Album_Cover.states =
playing:
scale: 1
shadowType: "outer"
shadowColor: "rgba(0,0,0,0.4)"
shadowY: 20
shadowSpread: 10
shadowBlur: 50
frame: $.Album_Cover.frame
animationOptions:
time: 0.8
curve: Spring(damping: 0.60)
paused:
scale: 0.8
shadowType: "outer"
shadowColor: "rgba(0,0,0,0.1)"
shadowY: 19
shadowSpread: 0
shadowBlur: 37
frame: $.Album_Cover.frame
animationOptions:
time: 0.5
I’ve also included the original frame
of the layer in each state. This is because, later on, we’ll add a third state for the mini-player in which we’ll change its position.
And I’ve also included animationOptions
:
- Animating to the
”playing”
state takes0.8
seconds, but it seems faster because it ends with a soft (dampened) bounce. - There’s no bounce when animating back to
”paused”
(we use the defaultBezier.ease
curve), and that animation’s duration is0.5
seconds.
To test the animations, we can stateCycle()
between them with a tap on the album cover:
$.Album_Cover.onTap ->
this.stateCycle "paused", "playing"
(By including their names the ”default”
state will be ignored.)
That looks okay.
You can delete the onTap()
event for now because we’ll trigger these state animations with the starting and stopping of the music.
With stateSwitch()
we can switch a layer to a certain state without animating it. We use this function to make ”paused”
the initial state.
$.Album_Cover.stateSwitch "paused"
Animating between the states when the music starts and stops
Now, we could use onTap
events on the “Play” and “Pause” buttons to trigger these animations, like this…
$.Button_Play.onTap ->
$.Album_Cover.animate "playing"
…but later we’ll have two more buttons: the ones on the mini-player.
So we’ll do it differently. We’re going to listen to the audio player’s playing
and pause
events.
The audio player has a player
object, which is the HTML5 audio element that actually plays the music. And apparently, we can add functions to it that will be run when an event occurs. You do this by creating a function in player
with an on
in front of the event name.
So playing
and pause
become onplaying
and onpause
.
# When the music started playing
audio.player.onplaying = ->
$.Album_Cover.animate "playing"
# When the music is paused
audio.player.onpause = ->
$.Album_Cover.animate "paused"
The state animations are now triggered by the music