Im making an Etch Sketch project using vanilla js. Im working on only coloring in cells on the grid when the mouse is being held down, in doing so I have added 2 event listeners to the grid container: one for mousedown events, and one for mouse up events. When I log anything inside these event listeners they are logged hundreds or thousands of times which isnt what I expect to be happening.
I also believe that these event listeners firing so many times is lagging out the whole site as when I change the slider value rapidly it takes time, sometimes even freezing the whole site.
My guess as to why this is happening is because the events are bubbling up the DOM, but from my understanding the events need to be of the same time to allow bubbling (which these events are not). Alas, I've tried a couple of things to solve this issue:
- I have made the mouse move event used for coloring a capture event rather than a bubble event
- I have tried using e.stopPropogation()
But neither of these have worked.
Any help on solving this would be greatly appreciated.
ps. the event listeners are set in the createGrid function.
const gridContainer = document.querySelector(".grid-container");
let cellColor = "black";
const gridWidth = gridContainer.offsetWidth;
const wipeGrid = () => {
gridContainer.innerHTML = "";
};
const colorCell = (cell, color) => {
return (cell.style.backgroundColor = `${color}`);
};
const createGrid = (numberOfCells) => {
const col = document.createElement("div");
col.className = "col";
for (let y = 0; y < numberOfCells; y++) {
const row = document.createElement("div");
row.className = "row";
for (let x = 0; x < numberOfCells; x++) {
const cell = document.createElement("div");
cell.style.cssText = `width:${gridWidth / numberOfCells}px; height:${
gridWidth / numberOfCells
}px;`;
cell.id = "cells";
let mouseDown = false;
gridContainer.addEventListener("mousedown", () => {
// console.log("down");
mouseDown = true;
cell.addEventListener("mousemove", () => {
if (mouseDown) {
colorCell(cell, cellColor);
}
});
});
gridContainer.addEventListener("mouseup", () => {
// console.log("up");
mouseDown = false;
});
row.appendChild(cell);
}
col.appendChild(row);
}
gridContainer.appendChild(col);
};
function ready(callback) {
if (document.readyState != "loading") callback();
else if (document.addEventListener)
document.addEventListener("DOMContentLoaded", callback);
else
document.attachEvent("onreadystatechange", function () {
if (document.readyState == "complete") callback();
});
}
ready(function () {
const slider = document.getElementById("slider");
createGrid(1);
slider.addEventListener("input", () => {
const sliderValue = document.querySelector(".thumb-value");
sliderValue.innerHTML = `${slider.value}`;
wipeGrid();
createGrid(slider.value);
});
});
* {
box-sizing: border-box;
padding: 0;
margin: 0;
font-family: 'Roboto', sans-serif;
--thumbNumber: '5';
}
.h-100vh {
height: 100vh;
}
.center-me {
display: flex;
align-items: center;
justify-content: center;
}
.grid-container {
border: 0.1px solid black;
height: 400px;
width: 400px;
}
.col {
display: flex;
flex-direction: column;
}
.row {
display: flex;
}
.gap-2em {
gap: 2em;
}
.gap-1em {
gap: 1em;
}
.title {
font-size: 7em;
margin:auto;
}
.input-label {
font-size: 1.25rem;
}
.slider {
-webkit-appearance: none;
width: 100%;
height: 25px;
border-radius: 5px;
background: #d3d3d3;
outline: none;
opacity: 1;
-webkit-transition: .2s;
transition: opacity .2s;
}
.slider:hover {
opacity: 0.7;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 25px;
height: 25px;
border-radius: 5px;
background: #1682FF;
cursor: pointer;
}
.slider::-webkit-slider-thumb::before {
content: var(--thumbNumber);
}
.range-div {
display:flex;
align-items: center;
gap:0.25em;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Etch a Sketch</title>
<meta name="description" content="" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Roboto:wght@900&family=Space+Mono&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="center-me h-100vh">
<div class="col gap-2em">
<p class="title">Etch a Sketch</p>
<div class="row gap-2em">
<div class="grid-container"></div>
<div class="col gap-1em">
<div class="slidecontainer col gap-1em">
<label for="slider" class="input-label"> GRID SIZE</label>
<div class="range-div">
<div class="thumb-value input-label">1</div>
<input
name="slider"
type="range"
min="10"
max="100"
value="1"
class="slider"
id="slider"
/>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="script.js" async defer></script>
</body>
</html>