I have a simple Mr Potato Head game with a big Mr Potato Head and a side bar filled with parts. I would like to make the parts, which are images, both draggable and resizable.
The following is the website code, with the dragAndResizeElement function responsible to add event listeners for both the dragging and resizing functionality. I call this function on every image when it is dynamically appended to the parent container of all the Mr. Potato Head parts. The dragging functionality works perfectly, however the resizing functionality does not work at all. I would love help in figuring out the best way to make these images dynamically resizable by the user. I have attached a picture of how the website looks on the screen since the code does not run properly without the folder of images in the directory.
<head>
<style>
body {
/*background-image: url(images/background3.jpg);*/
display: grid;
grid-template-columns: 25% 75%;
column-gap: 5em;
}
#mrPotatoHead {
width: 75%;
}
#bodyPartDiv {
border: 2px solid black;
}
.part {
max-width: 100%;
height: auto;
}
</style>
</head>
<body>
<audio xautoplay loop src="media/Children's Music - Kids Game.mp3"></audio>
<div id="bodyPartDiv"></div>
<img id="mrPotatoHead" src="images/mr-potato-head/body.png">
<script src="game.js"></script>
</body>
async function loadParts() {
try {
const response = await fetch('parts.json');
if (!response.ok) {
throw new Error(`${response.status} - ${response.statusText}`);
}
const json = await response.json();
return json.images;
} catch (e) {
console.error(e);
}
}
const parts = await loadParts();
parts.forEach(part => {
const img = document.createElement('img');
img.src = part;
img.className = 'part';
partDiv.append(img);
dragAndResizeElement(img);
});
function dragAndResizeElement(element) {
let dragging;
let resizing;
let translate = { x: 0, y: 0 };
let client = { x: 0, y: 0 };
let originalWidth, originalHeight;
element.addEventListener('mousedown', e => {
e.preventDefault();
if (e.offsetX > (element.offsetWidth - 20) && e.offsetY > (element.offsetHeight - 20)) {
element.style.cursor = 'nw-resize';
resizing = true;
originalWidth = element.offsetWidth;
originalHeight = element.offsetHeight;
}
else {
element.style.cursor = 'grabbing';
dragging = true;
}
client.x = e.clientX;
client.y = e.clientY;
});
document.addEventListener('mousemove', e => {
e.preventDefault();
if (dragging) {
translate.x = translate.x - (client.x - e.clientX);
translate.y = translate.y - (client.y - e.clientY);
element.style.transform = `translate(${translate.x}px, ${translate.y}px)`;
}
else if (resizing) {
const newWidth = originalWidth + (e.clientX - client.x);
const newHeight = originalHeight + (e.clientY - client.y);
element.style.width = `${newWidth}px`;
element.style.height = `${newHeight}px`;
}
client.x = e.clientX;
client.y = e.clientY;
});
document.addEventListener('mouseup', () => {
element.style.cursor = 'grab';
dragging = false;
resizing = false;
});
}