Make an Animated Record Player with me

SVG Animation Code Along

Lauren Birts
8 min readMay 28, 2020

Animations always makes my experience as a user 10x better. I feel like animations make websites feel alive and give it a human-like pulse. I decided to make one and needed a refresher, so we can figure this out together.

When you are creating your animation, you must decide what you are trying to say and do because there are many ways to animate. For this tutorial, we will be using a vector image from Vector4Free. We will also be using CSS, SVG, and Javascript to animate. SVG stands for Scalable Vector Graphic. It is excellent for small graphics; designers usually use this for logo creation. If you have something more minor like sliding panels or expanding divs, I recommend just using CSS.

Let’s get started! This is how our image looks as of now.

Step 1: Group vectors

Open your vector on whatever platform you are comfortable using. I am using Illustrator.

For starters, we need to group the vectors we want to animate. In this case, I want to animate the needle, the record, and the volume. To group them, you hold shift while selecting the vectors you want.

Name your groups for ease later. Besides grouping, I also removed the background, an extra button, and changed the color of a small rectangle that symbolizes whether the record player is on or not (we want to start with it off, so I changed the color to grey)

After you’ve grouped everything and you are comfortable, you can export your file. Click on File then Save As. In the drop-down menu of format, select SVG and name it to your liking and click Save.

A new window will pop up, and at the very bottom, we are going to click SVG code. This will give you a text document of all your SVG code. Please don’t be intimidated by the length of the material. Copy and paste it inside the body tag of your HTML file. View it in your browser to make sure your image displays.

Once we have all of our code in our HTML file, we will be able to collapse all the groups based on the grouping/naming conventions we did earlier and expand the groups we need (names are the id’s of the vectors grouped). This will allow us to navigate easier.

Go ahead and create a CSS file, add some minimal styling, and link your CSS file to your HTML file.

For starters, we are going to change our background-color.

body {
background: #293F4F
}

Our picture look like this now.

LET’S ANIMATE!!

Step 2: Spin the disk.

To start, we are going to work on making the record spin. This should be a smooth animation. Let’s create an animation named “spin.”

CSS animations contain two main components: keyframes (which defines the animation) and animation properties (which assigns the animation).

Let’s begin with keyframes.

@keyframes spin {
0% {
transform: rotate(0deg);
}
50% {
transform: rotate(180deg);
}
100% {
transform: rotate(360deg);
}
}

Keyframes have the name of the animation, stages, and CSS properties

  • spin is the name of the animation
  • 0%, 50%, and 100% are the stages of the animation (when I want the animation to take place) 0 representing the beginning, 100 representing the end
  • transform: rotate(ndeg); is the CSS property defined for each stage of the animation

Now the CSS properties i.e., transform is where the magic happens. You can do something as simple as changing the color of your element. Or you can transform your element using CSS properties like:

  • transform: skew()
  • transform: translate()
  • transform: scale()
  • transform: rotate()
  • opacity

Here is a link of animatable CSS properties for your viewing pleasure :)

So now you’ve made your CSS animation, but how do we get it to work?

This is where animation properties come in (assign keyframes to elements and define how it is animated). But I already thought we defined how it was animated in keyframes??? Nope, earlier, we defined how the animation looks. To get any animation started in CSS, you need the animation name and the animation duration.

#Record {
animation-duration: 9s;
animation-name: spin;
}
/* shorthand */
#Record {
animation: 9s spin 5s infinite linear;
}

We assign a keyframe with animation-name and give the duration (how long we want one cycle of the animation) of the animation in milliseconds with animation-duration (i.e., 9s). You may notice we added three other animation properties. The ‘5s’ just says we want to start the animation in 5-milliseconds. We gave it a 5-millisecond delay because we need time for the needle to move to the record. Infinite says we don’t want it to stop, and linear is the velocity of our animation (I recommend researching the timing functions a little more to understand what each one does). We can also add an animation direction.

If you’ve tested what we have so far in your browser, you can see this isn’t quite right, the record is rotating all across the screen, we need it to rotate only on the record player. This can be fixed by adding a transform-origin. Transform-origin is just the origin position of our transformation (kind of like an axis).

#Record {
transform-origin: 355px 300px;
animation: 9s spin 5s infinite linear;
}

This would be the usual way we animate things. However, since we are using a SVG, we can put all the animation directly in the HTML document.

<animateTransform xlink:href=”#Record” attributeName=”transform” type=”rotate” from=”0" to=”360" begin=”Start_Stop.click + 5s” dur=”9s” id=”record-anim” repeatCount=”indefinite”/>
  • xlink:href is where we assign the element we want to animate
  • attributeName is the name of the animation (i.e., transform, fill, opacity)
  • type is the type of animation (usually only needed for transform animations)
  • from is where the animation starts
  • to is where the animation ends
  • begin is when the animations starts (i.e., 3s, click, mouse)
  • dur is the duration of the animation
  • id is what we are naming the animation
  • repeatCount is how many times the animation will play for (i.e., indefinite, 1)

All of this basically says is we want the record to rotate 360 degrees indefinitely for 9-milliseconds only 5-milliseconds after we click a button. We can take the animation property out of the CSS file, and it would still work the same way. Sidenote: if we weren’t using a transform animation, the tag would just be <animate/>.

Yayy we did it!!

Step 3: Move the needle

Now that we got the record to spin let’s get the needle to move. I had to test this a lot to figure out what values moved the needle to my liking. Just for time sake, I ended up with this:

@keyframes move-needle {
0%{
transform: rotate(0deg);
}
100% {
transform: rotate(45deg);
}
}

and

#Needle {
transform-origin: 655px 175px;
animation: move-needle 5s forwards;
}

This time we only used forwards because we wanted it to happen only once in one the forwards direction. I included the animate shorthand for those interested in both ways.

<animateTransform xlink:href=”#Needle” attributeName=”transform” type=”rotate” from=”0" to=”45" begin=”Start_Stop.click” dur=”5s” fill=”freeze” id=”needle-anim” repeatCount=”1"/>

and

#Needle {
transform-origin: 655px 175px;
}

Step 4: Move the volume knob

Next, we are going to move the volume knob up to the middle of the volume section. We don’t need a transform-origin for our volume notch because we are just moving it up and down

@keyframes turn-up {
0% {
transform: translateY(0px);
}
100% {
transform: translateY(-64px);
}
}

and

#VolumeKnob {
animation: turn-up 3s forwards;
}

OR

<animateTransform xlink:href=”#VolumeKnob” attributeName=”transform” type=”translate” from=”0 0" to=”0 -64" begin=”Start_Stop.click” dur=”3s” fill=”freeze” repeatCount=”1" id=”knotch-anim”/>

Step 5: Rotate Axis

Lastly, let’s go ahead and rotate our axis as well to make it look more real. We can use the same spin keyframe we made earlier for the axis so it would look something like this:

#Axis {
transform-origin: 353px 299px;
animation: 1s spin 5s infinite linear;
}

OR

<animateTransform xlink:href=”#Axis” attributeName=”transform” type=”rotate” from=”0" to=”360" begin=”Start_Stop.click + 5s” dur=”2s” id=”axis-anim” repeatCount=”indefinite”/>

and

#Axis {
transform-origin: 353px 299px;
}

This is our end product. I made small additions to change the color of the volume levels when clicking the start button. To change colors in SVG, we need to use fill instead of background. I also made the reverse button work, so now the record turns in the opposite direction. I just added a reverse animation and changed the to value to -360.

Future Implementations

I would like to add music, so when we click the start button music plays. I ended up making the volume knob draggable. This can be done by adding the following script tags to your HTML file:

<script src=”https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.6/gsap.min.js"></script><script src=”https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.6/Draggable.min.js"></script>

and this to your Javascript file:

Draggable.create(“#dragKnob”, { type:”y”, bounds:”#VolumeSpace”});

But the volume levels need to be synced with the draggable knob, so every time we move the knob, the volume lights move with it. More info about Draggable can be found here.

Conclusion

Overall, this was pretty fun to make. I think I preferred the CSS animation over SVG, but it was refreshing to know that I didn’t have to add onclick events in Javascript to get the animation to start (the SVG shorthand did that for us). Though, I did notice I couldn’t stop the SVG animation by clicking the button again. I would’ve had to make another button to stop the animation. When I tried to animate it with Javascript and the toggleClass property, the start/stop button worked as anticipated. However, using Javascript, I noticed when I clicked the reverse button on and off, there was a delay in the continuation of the previous animation because we gave both the record and the axis a 5-millisecond delay in-order for the needle to catch up. When I took the delay off, it worked perfectly, but starting the record without delay looked weird. I didn’t have this problem using SVG. I guess there are pros and cons to each. Let me know in the comments if anyone has a fix for either the stop issue with SVG or the reverse issue with Javascript.

Did you enjoy this post? Let me know if you want more ‘code with me’ tutorials. Follow me to stay up-to-date on my tech journey, via Lauren Marie.

--

--