Subscribe

Draggable Mr Potato Head Parts in JavaScript πŸ₯”

✍️

Learn how to recreate the iconic Mr. Potato head in JavaScript by dragging parts to other positions on the screen canvas! See the example in Codepen!

3 Oct, 2020 Β· 5 min read

Who doesn't like Mr. and Mrs. Potato Head!

Today we will recreate the iconic Mr. Potato Head in JavaScript. Then we will learn to drag all of Mr. Potato Heads parts on the screen to his body.

Mr. Potato Head

Try the example code on Codepen

See the Pen Vanilla JavaScript draggable Mr Potato Head πŸ₯” by Chris Bongers (@rebelchris) on CodePen.

HTML Structure

As for our HTML, we have the following setup.

<div class="container">
  <div class="parts">
    <img src="https://i.imgur.com/GONNbHf.png" class="draggable" />
    <img src="https://i.imgur.com/optSzq4.png" class="draggable" />
    <img src="https://i.imgur.com/qJDxc4o.png" class="draggable" />
    <img src="https://i.imgur.com/tIZGoeR.png" class="draggable" />
    <img src="https://i.imgur.com/bKlbeXU.png" class="draggable" />
    <img src="https://i.imgur.com/eUPbX3H.png" class="draggable" />
    <img src="https://i.imgur.com/voJPsR5.png" class="draggable" />
    <img src="https://i.imgur.com/dt2gqit.png" class="draggable" />
    <img src="https://i.imgur.com/2POeyJZ.png" class="draggable" />
  </div>
  <div class="body">
    <img src="https://i.imgur.com/kXbr8Tb.png" />
  </div>
</div>

So we use the container to wrap all image tags. Then we have the Mr. Potato Head parts div. It contains each body part with a class of draggable.

And we have our body, which is Mr. Potato's body. The body is where we want to drag the elements with JavaScript.

CSS Styling

We use flexbox to center our two divs.

.container {
  display: flex;
  align-items: center;
  justify-content: space-around;
  min-height: 100vh;
  background: #efefef;
}

The Parts container is then relative, and we add a small border to make it look nicer.

.container .parts {
  position: relative;
  border: 3px dashed black;
  width: 250px;
  height: 100vh;
}

Each PNG will be absolute so we can place it anywhere on the page.

.container .parts img {
  position: absolute;
}

Vanilla JavaScript draggable Mr. Potato Head elements

To make an actual Mr. Potato Head, we need to make sure all the HTML elements for his body parts are draggable!

I did not use the draggable element since that requires a dropzone, and it doesn't serve this article.

Let's start by getting our elements with the class draggable.

const draggableElements = document.querySelectorAll('.draggable');

Then we need to define four essential variables. We will use them to store our position. We also add a whichDown variable to see which element is dragging.

let initX, initY, firstX, firstY, whichDown;

Next on our list is to loop over each element.

draggableElements.forEach((element) => {
  // Code here
});

Then we need to attach a mousedown event listener. This will be our starting point. We will define the current x and y position using offsetLeft and offsetTop. Then we get the mouse positions x and y.

And we attach an event listener to mousemove since that will be us, dragging apart. Once we move our mouse, we call the draggable function, which we will make in a second.

draggableElements.forEach((element) => {
  element.addEventListener('mousedown', function (e) {
    e.preventDefault();
    whichDown = this;
    initX = this.offsetLeft;
    initY = this.offsetTop;
    firstX = e.pageX;
    firstY = e.pageY;
  });
});

window.addEventListener('mousemove', draggable, false);

Let's get started with our JS function to drag elements on the screen.

All this function does is change the left and top positions of our part. And Set the z-index higher, so it's on top.

function draggable(e) {
  e.preventDefault();
  if (!whichDown) return;
  whichDown.style.zIndex = 9;
  whichDown.style.left = initX + e.pageX - firstX + 'px';
  whichDown.style.top = initY + e.pageY - firstY + 'px';
}

We calculate the element's original position + the dragged amount - the initial mouse x. And the same goes for the y position.

That's cool, but we cannot stop it now. So let's add a mouseup listener.

window.addEventListener(
  'mouseup',
  function () {
    if (whichDown) {
      whichDown.style.zIndex = 0;
    }
    whichDown = null;
  },
  false
);

In this section, we add a mouseup event to our window, and once that happens, we remove the z-index from our dragging element and remove the draggable which down element.

That is it. We can now drag HTML elements on the screen as showcased on Mr. Potato Head's body!

Thank you for reading, and let's connect!

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter

Spread the knowledge with fellow developers on Twitter
Tweet this tip
Powered by Webmentions - Learn more

Read next πŸ“–

TypeORM viewEntity

30 Mar, 2022 Β· 5 min read

TypeORM viewEntity

The Record Utility Type in TypeScript

12 Mar, 2022 Β· 3 min read

The Record Utility Type in TypeScript

Join 1372 devs and subscribe to my newsletter