Needledrop: A turntable interface for music playback

Needledrop

My latest experiment is Needledrop, a turntable interface for playing music from YouTube. Enjoy chill vibes as you spin a virtual vinyl of your favorite album from YouTube. You can try it for yourself here:

With Needledrop, I went for the Dieter Rams school of design. It’s inspired by unapologetically skeuomorphic interfaces like Apple’s original Podcasts app, which featured a reel-to-reel tape machine. While I preferred the digitally native approach of Overcast for day-to-day use, Apple’s approach was visually striking.

Podcast’s interface wasn’t just veneer; the reels would progress as the podcast did, providing a subtle visual cue alongside the progress bar. Likewise in Needledrop, the tone arm travels across the record.

But Needledrop takes the interactivity one step further. Drop the needle and find your favorite track, more or less. It’s fuzzy and inexact, and emphasizes the continuous listening experience an album can be.

Pick Your Track

Click the “Track” button, paste the link to your favorite album from YouTube, and it’ll load on the platter. You can bookmark the URL for easy access and share it with friends.

A few quick picks:

Singles and podcasts work, and streams like lofi hip hop radio sorta work. And of course the needle drop.

Fun fact: podcasts have actually been pressed on vinyl.

Hello Internet

Skeuomorphic Effects in CSS

Of course this post wouldn’t be complete if I didn’t geek out on implementation details.

First, to achieve spinning record, the following CSS animation was used. The 1.8 second duration corresponds with 33 1/3 rpm.


#record {
  animation: spin 1.8s infinite linear;
}

@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(359deg);
  }
}

To pause the animation when the “Stop” button is tapped, I first tried animation: none;. I quickly noticed that when you resume play, the animation will reset and the record jumps back to its initial position. To smooth out the animation, use this instead:


.pause #record {
  animation-play-state: paused;
}

Needledrop can switch between 33 and 45 rpm. When changing the animation duration to account for this, I ran into a similar problem with the spinning animation being jerky. This happened even if I used a CSS variable like animation-duration: var(--duration);.

To work around this, I nested two elements. When the mode is changed to 45 rpm, the second element activates a spin animation as well. After some quick maths, I set the duration of the second spin to 5.1428 seconds.

I also offset the rotation slightly with transform-origin, creating a slight wobble effect.

To finish the record’s styles, I added grooves with:


background: repeating-radial-gradient(var(--record-color),
                                      var(--record-groove-color) 3px,
                                      var(--record-groove-color) 3px);

Needledrop Record

I also gave it a shine by positioning an element over the record with a conic background. A separate element was used so the shine wouldn’t rotate with the record.


background: conic-gradient(transparent 20deg,
                           rgba(255, 255, 255, .1) 40deg,
                           rgba(255, 255, 255, .1) 50deg,
                           transparent 60deg,
                           transparent 200deg,
                           rgba(255, 255, 255, .08) 220deg,
                           rgba(255, 255, 255, .08) 240deg,
                           transparent 250deg,
                           transparent 340deg);

To move the arm of the record player, I used transform: rotate(45deg); and set a transition delay, calculating how long it should take for the arm to reach its final position in JavaScript.

YouTube API

Needledrop is built using the YouTube Player API.

The API makes it easy to speed up the video when set to 45 rpm, among other things:


player.setPlaybackRate(1.35);

Of course when you’re using a third-party API, you’re beholden to their terms of service. In this case, the key sections of Google’s TOS are:

You and your API Clients must not, and must not encourage, enable, or require others to:

6. modify, build upon, or block any portion or functionality of a YouTube player;

7. separate, isolate, or modify the audio or video components of any YouTube audiovisual content made available as part of, or in connection with, YouTube API Services. For example, you must not apply alternate audio tracks to videos;

8. promote separately the audio or video components of any YouTube audiovisual content made available as part of, or in connection with, the YouTube API Services;

9. create, include, or promote features that play content, including audio or video components, from a background player, meaning a player that is not displayed in the page, tab, or screen that the user is viewing;

So yeah. Hiding the video so only the audio track is used was definitely out. To the label it goes. As for the rest, we’re probably pushing it.

Anyway, much of digital design is influenced by its analog analogue. It was fun to bring that to the foreground with Needledrop.

As far as next steps, stay tuned for YouTube playlist and Spotify support.

5 comments Write a comment

  1. Super fun! Thank you. Wish the clipping worked in Safari. Perhaps add to #record-inner…

    overflow: hidden;
    border-radius: 50%;

  2. This is a neat idea and execution!

    That aside, not gonna lie, I was looking for a grain effect toggle.

    Good work! I want to know what my dad thinks of it.

Leave a Reply