DEV Community

Cover image for Mapping the Sky: GPS Receiver Animation
Rodrigo Antunes
Rodrigo Antunes

Posted on • Edited on

Mapping the Sky: GPS Receiver Animation

I love the "Something in 100 Seconds" series from Fireship, and the recent episode, "Scala in 100 Seconds," caught my attention. Not only was the content on Scala interesting, but there was also a sponsor video that intrigued me, which you can see at 2:51.

I wondered if I could recreate the animation featured in that video, so I gave it a try. Here’s my attempt:

HTML

For the first time, I used a <datalist> element to display ticks below the input range element. It doesn’t look exactly like the original, but it’s a close approximation using a native solution.

<input type="range" min="0" max="100" value="0" list="markers">

<datalist id="markers">
  <option value="0"></option>
  <option value="10"></option>
  <option value="20"></option>
  <option value="30"></option>
  <option value="40"></option>
  <option value="50"></option>
  <option value="60"></option>
  <option value="70"></option>
  <option value="80"></option>
  <option value="90"></option>
  <option value="100"></option>
</datalist>
Enter fullscreen mode Exit fullscreen mode

This gives us these little markers

datalist

For the animatable elements, I decided to apply the images via the style attribute so that my CSS is responsible only for positioning:

<div class="container"
  style="background-image: url('https://res.cloudinary.com/rodrigoantunes/image/upload/v1723209932/stars.jpg')">

  <div class="globe"
    style="background-image: url('https://res.cloudinary.com/rodrigoantunes/image/upload/v1723210573/flatmap.jpg');">
  </div>

  <div class="satellite"
    style="background-image: url('https://res.cloudinary.com/rodrigoantunes/image/upload/v1723213814/particules.png');">
  </div>

</div>

Enter fullscreen mode Exit fullscreen mode

CSS

The CSS is mostly straightforward, but I’d like to highlight the use of aspect-ratio. This allowed me to avoid hardcoding many values and keep my code DRY:

.globe {
  height: 130px;
  /* width: 130px; */
  aspect-ratio: 1
}
Enter fullscreen mode Exit fullscreen mode

Or when using width: 100% but still wanting to maintain the aspect ratio without forcing it with hardcoded equations:

.container {
  width: 100%;
  /* height: 333px; */
  aspect-ratio: 3/2;
}
Enter fullscreen mode Exit fullscreen mode

Javascript

Here I had to set initial values to prevent the animations from "jumping" when the input element is triggered. I also performed some logical operations to make the range from 0 to 100 behave like in the video, converting some values to negative:

const range = document.querySelector('input[type=range]');

// Initial values
const initialValue = parseInt(range.value, 10);
const initialContainerPosition = initialValue / -3;
const initialGlobePosition = initialValue;
const initialSatellitePosition = -initialValue - 40;

Enter fullscreen mode Exit fullscreen mode

Then, it was just a matter of adjusting and refining the positions and directions:

range.addEventListener('input', (e) => {
  const containerPosition = e.target.value / -3;
  const globePosition = e.target.value;
  const satellitePosition = -e.target.value - 40;

  container.style.backgroundPositionX = `${containerPosition}%`;
  globe.style.backgroundPositionX = `${globePosition}%`;
  satellite.style.transform = `translateX(${satellitePosition}%)`;
});

Enter fullscreen mode Exit fullscreen mode

It's not an exact replica, but I'm happy with the result using native HTML, CSS, and JavaScript. Feedback and suggestions are welcome!

By the way, I’ve created a GitHub org where I keep these posts. By following, you’ll receive updates in your GitHub feed whenever there's a new post. Feel free to give it a follow 😁

GitHub

Top comments (0)