Hey there, I'm currently working on a simple prototype for an app. The concept is straightforward: there is a box, and when you click on it, it creates a square that changes color when clicked on.
The issue I'm facing is that when I click on the box to generate the square, it appears below the box, which is not the desired behavior.
Below is the complete code snippet:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
<style type="text/css">
body {
margin: 0;
padding: 0;
background-color: #27293F;
}
#title {
width: 100vw;
height: 20vh;
}
h1 {
width: 100%;
color: #4FFF5A;
text-align: center;
}
p {
width: 100vw;
color: #379A3D;
text-align: center;
}
#plants {
width: 100vw;
height: 75vh;
border: 10px solid #FF5555;
display: flex;
flex-wrap: wrap;
}
.plant {
position: static;
width: 50px;
height: 50px;
}
</style>
<script src="Plant.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<section id="title">
<h1>The plant generator 🌱</h1>
<p>click anywhere in the box to generate a plant</p>
</section>
<div id="plants">
</div>
<script type="text/javascript" charset="utf-8">
const colors = ['red', 'blue', 'green'];
const plantsContainer = document.getElementById('plants');
plantsContainer.addEventListener('mousedown', function(event) {
generatePlant(event.x, event.y, plantsContainer);
});
/**
* Changes the plant's color on click.
* @param {Plant} plant Target to change the color.
* @param {HTMLDivElement} plantElement The plant element.
* @returns undefined
*/
function changeColorOnClick(plant, plantElement) {
let index = plant.getState().colorIndex + 1;
index >= colors.length ? index = 0 : null;
plant.setState({ ...plant.getState(), color: colors[index], colorIndex: index });
plantElement.style.backgroundColor = plant.getState().color;
}
/**
* Generate a plant.
* @param {Number} x The plant's x cordinate.
* @param {Number} y The plant's y cordinate.
* @param {any} appendAt? The element to append the plant at.
* @returns {Plant}
*/
function generatePlant(x, y, appendAt) {
let plant = new Plant();
x = x ?? Math.floor(Math.random() * window.innerWidth);
y = y ?? Math.floor(Math.random() * window.innerHeight);
generatePlantElement(plant, x, y);
console.log(x, y);
return plant;
}
/**
* Generate a plant element.
* @param {Plant} plant The plant.
* @param {Number} x The plant's x cordinate.
* @param {Number} y The plant's y cordinate.
* @param {any} appendAt? The element to append the plant element at [optional].
*/
function generatePlantElement(plant, x, y, appendAt) {
let plantElement = document.createElement("div");
let plantState = plant.getState();
plantElement.classList.add("plant");
plantElement.style.marginLeft = `${x}px`;
plantElement.style.marginTop = `${y}px`;
plantElement.style.backgroundColor = plantState.color;
(appendAt || document.body).appendChild(plantElement);
plantElement.onclick = () => changeColorOnClick(plant, plantElement);
}
</script>
</body>
</html>
Plant.js:
window.Plant = class Plant {
/**
* @param {Object} state? Custom state [optional].
*/
constructor(state) {
this.state = state || { color: 'red', colorIndex: 0, waterable: true, watered: false };
}
/**
* Changes the plant's state.
* @param {Object} state Custom state.
* @returns {Object}
*/
setState(state) {
this.state = (state ?? this.state) ?? { color: 'red', colorIndex: 0, waterable: true, watered: false };
return this.state;
}
/**
* Returns the plant's state
* @returns {Object}
*/
getState() {
return this.state ?? { color: 'red', colorIndex: 0, waterable: true, watered: false }
}
/**
* Stringify the plant's state.
* @returns {String}
*/
toString() {
return JSON.stringify(this.state);
}
}
I have experimented with various solutions such as using transforms, negative y values, etc. Unfortunately, none of them provided the desired result...
If you have any suggestions on how to fix this issue, I would greatly appreciate it! 👍