Draggable Mr Potato Head Parts in JavaScript πŸ₯”

β€” 9 minute read

permalink

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

Today we will recreat 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 permalink

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

HTML Structure permalink

As for out HTML, we have a fairly simple 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 of the body-parts 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 permalink

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 in the page.

.container .parts img {
position: absolute;
}

Vanilla JavaScript draggable Mr. Potato Head elements permalink

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 basic variables. We will use them to store our position in. 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 eventListener. This will be our starting point. We will define the current x and y position by using offsetLeft and offsetTop. Then we get the mouse position x and y.

And we attach an eventListener too mousemove since that will be us, dragging a part. 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 position 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 original position of the element + the dragged amount - the initial mouse x. And the same goes for the y position.

That's cool, but we have no way of stopping it dragging 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 whichDown 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! permalink

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