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.
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
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
- The shadow’s color is 40% black —
- The shadow is projected downwards —
- … but also outwards in all directions — a
- (There’s no
- The shadow’s blur is also high —
50points of Gaussian blur
And when the music is paused, it should look like this:
- The album is 249 x 249 — which makes for a
- The shadow is very light: only 10% black —
(The shadow will actually end up being 20% smaller because of the scale change.)
To keep it simple we’ll call our states
"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
- Animating to the
0.8seconds, but it seems faster because it ends with a soft (dampened) bounce.
- There’s no bounce when animating back to
”paused”(we use the default
Bezier.easecurve), and that animation’s duration is
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.
stateSwitch() we can switch a layer to a certain state without animating it. We use this function to make
”paused” the initial state.
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
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.
# 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