DEV Community

Cover image for How to Recreate the Iconic Pegman from Google Maps
Rodrigo Antunes
Rodrigo Antunes

Posted on

How to Recreate the Iconic Pegman from Google Maps

This is a little snippet I’ve wanted to try for quite some time. I finally got around to recreating this iconic feature from Google Maps: the ability to drag and drop this little guy, known as Pegman, to switch to Street View.

TL;DR
Click and drag the little icon in the bottom-right corner over the map:

HTML

The structure is straightforward. I have:

  • A #map to serve as the container (with a background-image applied).
  • A #pegman-container positioned in the bottom-right corner.
  • The #pegman element itself for the draggable character.
<div id="map">
  <div id="pegman-container">
    <div id="pegman"> </div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

CSS

Positioning everything is simple, as you can see in the source code above, but the most important part is the rotate property. This is dynamically updated using JavaScript:

#pegman {
  /* other styles */
  rotate: var(--r);
}
Enter fullscreen mode Exit fullscreen mode

The rotate value changes based on user interaction, which we’ll dive into next.

Javascript

Everything here revolves around user interaction. JavaScript handles:

  • Listening for mouse events.
  • Updating Pegman’s position and rotation dynamically.
  • Adding smooth animations for better UX.
const pegman = document.querySelector('#pegman');
let isDragging = false;
let initialX = 0;
let initialY = 0;
let inactivityTimeout;
let lastX = 0;
const timeout = 25;
const maxDegrees = 50;

// Event listeners
pegman.addEventListener('mousedown', onMouseDown);
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
Enter fullscreen mode Exit fullscreen mode

Let’s break down each function:

onMouseDown

This starts the drag by recording the initial mouse position and toggling the isDragging flag.

const onMouseDown = (e) => {
  isDragging = true;
  initialX = e.clientX;
  initialY = e.clientY;
};
Enter fullscreen mode Exit fullscreen mode

onMouseMove

This handles Pegman’s movement and rotation during the drag. It ensures:

  • Rotation stays within a range (to avoid extreme angles like Superman flying).
  • The rotate value updates dynamically using --r.
const onMouseMove = (e) => {
  if (!isDragging) return;

  const dy = e.clientY - initialY;
  const dx = e.clientX - initialX;

  // Limit rotation range
  let rx = Math.max(-maxDegrees, Math.min(maxDegrees, dx - lastX));
  pegman.setAttribute('style', `--r: ${rx}deg`);

  // Animate Pegman's position
  pegman.animate({ translate: `${dx}px ${dy}px` }, {
    duration: 100,
    fill: 'forwards',
  });

  // Reset rotation after inactivity
  clearTimeout(inactivityTimeout);
  inactivityTimeout = setTimeout(() => {
    lastX = dx;
    pegman.setAttribute('style', `--r: 0deg`);
  }, timeout);
};

Enter fullscreen mode Exit fullscreen mode

onMouseUp

This resets Pegman’s state once the user stops dragging:

  • Rotation resets to 0.
  • Pegman smoothly returns to its original position.
const onMouseUp = () => {
  isDragging = false;

  // Reset rotation
  pegman.setAttribute('style', `--r: 0`);

  // Animate Pegman back to its original position
  pegman.animate({ translate: `0px 0px` }, {
    duration: 500,
    fill: 'forwards',
    easing: 'ease',
  });

  // Clear residual state
  inactivityTimeout = setTimeout(() => {
    lastX = 0;
  }, timeout);
};
Enter fullscreen mode Exit fullscreen mode

Final Thoughts

This snippet highlights how simple animations and interactivity can recreate an iconic user experience. Key takeaways:

  • Using CSS custom properties (like --r) keeps styling dynamic and manageable.
  • Rotation limits ensure a polished, natural feel for user interactions.
  • Timeouts and easing animations add realism to the motion.

Feel free to fork the CodePen, make changes and let me know what you think! 🚀🗺️

By the way...

I'm using the original sprites from google, which you can see here and make experiments:

Did you know? ✨ The Google Maps location I used is the real Santa Claus Village!
Fun fact: Santa’s Finnish name is Joulupukki, and he originally from Finland 🎅🏻🎄

Top comments (2)

Collapse
 
eldar_soltanov767 profile image
Eldar Soltanov

I thought Santa Claus was from Türkiye.

Collapse
 
rodrigoantunes profile image
Rodrigo Antunes

Interesting, didn't know that! Thanks for the info. Looks like Santa’s got roots in both Saint Nicholas from Turkey and Joulupukki in Finland! 🎅✈️