Video Tutorial:
If you like to code along to a video tutorial rather than reading this blog post, you can check out the video version of this tutorial here down below. If you find this tutorial interesting, subscribe to my youtube channel. I post new tutorials on web development regularly there. Along with that, I also keep you updated with the latest tips and tricks.
Project Folder Structure:
Before we start the coding, let us take a look at the project folder structure. We create a project folder called – ‘Pixel Art Maker’. Within this folder, we have three files- index.html, style.css and script.js.
HTML:
We begin with the HTML code. Firstly copy the code provided to you below and paste it into your HTML document. We create the elements necessary for the layout using HTML.
<!DOCTYPE html> <html lang="en"> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Pixel Art Generator</title> <!-- Google Fonts --> <link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@500&display=swap" rel="stylesheet" /> <!-- Stylesheet --> <link rel="stylesheet" href="style.css" /> </head> <body> <div class="wrapper"> <div class="options"> <div class="opt-wrapper"> <div class="slider"> <label for="width-range">Grid Width</label> <input type="range" id="width-range" min="1" max="35" /> <span id="width-value">00</span> </div> <div class="slider"> <label for="height-range">Grid Height</label> <input type="range" id="height-range" min="1" max="35" /> <span id="height-value">00</span> </div> </div> <div class="opt-wrapper"> <button id="submit-grid">Create Grid</button> <button id="clear-grid">Clear Grid</button> <input type="color" id="color-input" /> <button id="erase-btn">Erase</button> <button id="paint-btn">Paint</button> </div> </div> <div class="container"></div> </div> <!-- Script --> <script src="script.js"></script> </body> </html>
CSS:
Next, we style these elements using CSS. Now copy the code below and paste it into your stylesheet.
* { padding: 0; margin: 0; box-sizing: border-box; font-family: "Roboto Mono", monospace; } body { background-color: #f4c531; } .wrapper { background-color: #ffffff; width: 80vmin; position: absolute; transform: translate(-50%, -50%); top: 50%; left: 50%; padding: 40px 20px; border-radius: 8px; } label { display: block; } span { position: relative; font-size: 22px; bottom: -1px; } .opt-wrapper { display: flex; justify-content: space-between; margin-bottom: 20px; gap: 10px; } button { background-color: #f4c531; border: none; border-radius: 5px; padding: 5px; } input[type="color"] { -webkit-appearance: none; -moz-appearance: none; appearance: none; background-color: transparent; width: 70px; height: 40px; border: none; cursor: pointer; } input[type="color"]::-webkit-color-swatch { border-radius: 8px; border: 4px solid #000000; } input[type="color"]::-moz-color-swatch { border-radius: 8px; border: 4px solid #000000; } .gridCol { height: 1em; width: 1em; border: 1px solid #ddd; } .gridRow { display: flex; } @media only screen and (max-width: 768px) { .gridCol { height: 0.8em; width: 0.8em; } }
Javascript:
Lastly, we implement the functionality using javascript. Once again copy the code below and paste it into your javascript file. We implement the logic in six steps. The steps are as follows:
1. Create the initial references.
2. Create an events object.
3. Function to detect touch device.
4. Function to create the grid.
5. Add event listeners to clear grid, erase and paint button.
6. Display grid height and width.
//Initial references let container = document.querySelector(".container"); let gridButton = document.getElementById("submit-grid"); let clearGridButton = document.getElementById("clear-grid"); let gridWidth = document.getElementById("width-range"); let gridHeight = document.getElementById("height-range"); let colorButton = document.getElementById("color-input"); let eraseBtn = document.getElementById("erase-btn"); let paintBtn = document.getElementById("paint-btn"); let widthValue = document.getElementById("width-value"); let heightValue = document.getElementById("height-value"); //Events object let events = { mouse: { down: "mousedown", move: "mousemove", up: "mouseup", }, touch: { down: "touchstart", move: "touchmove", up: "touchend", }, }; let deviceType = ""; //Initially draw and erase would be false let draw = false; let erase = false; //Detect touch device const isTouchDevice = () => { try { //We try to create TouchEvent(it would fail for desktops and throw error) document.createEvent("TouchEvent"); deviceType = "touch"; return true; } catch (e) { deviceType = "mouse"; return false; } }; isTouchDevice(); //Create Grid gridButton.addEventListener("click", () => { //Initially clear the grid (old grids cleared) container.innerHTML = ""; //count variable for generating unique ids let count = 0; //loop for creating rows for (let i = 0; i < gridHeight.value; i++) { //incrementing count by 2 count += 2; //Create row div let div = document.createElement("div"); div.classList.add("gridRow"); //Create Columns for (let j = 0; j < gridWidth.value; j++) { count += 2; let col = document.createElement("div"); col.classList.add("gridCol"); /* We need unique ids for all columns (for touch screen specifically) */ col.setAttribute("id", `gridCol${count}`); /* For eg if deviceType = "mouse" the statement for the event would be events[mouse].down which equals to mousedown if deviceType="touch" the statement for event would be events[touch].down which equals to touchstart */ col.addEventListener(events[deviceType].down, () => { //user starts drawing draw = true; //if erase = true then background = transparent else color if (erase) { col.style.backgroundColor = "transparent"; } else { col.style.backgroundColor = colorButton.value; } }); col.addEventListener(events[deviceType].move, (e) => { /* elementFromPoint returns the element at x,y position of mouse */ let elementId = document.elementFromPoint( !isTouchDevice() ? e.clientX : e.touches[0].clientX, !isTouchDevice() ? e.clientY : e.touches[0].clientY ).id; //checker checker(elementId); }); //Stop drawing col.addEventListener(events[deviceType].up, () => { draw = false; }); //append columns div.appendChild(col); } //append grid to container container.appendChild(div); } }); function checker(elementId) { let gridColumns = document.querySelectorAll(".gridCol"); //loop through all boxes gridColumns.forEach((element) => { //if id matches then color if (elementId == element.id) { if (draw && !erase) { element.style.backgroundColor = colorButton.value; } else if (draw && erase) { element.style.backgroundColor = "transparent"; } } }); } //Clear Grid clearGridButton.addEventListener("click", () => { container.innerHTML = ""; }); //Erase Button eraseBtn.addEventListener("click", () => { erase = true; }); //Paint button paintBtn.addEventListener("click", () => { erase = false; }); //Display grid width and height gridWidth.addEventListener("input", () => { widthValue.innerHTML = gridWidth.value < 9 ? `0${gridWidth.value}` : gridWidth.value; }); gridHeight.addEventListener("input", () => { heightValue.innerHTML = gridHeight.value < 9 ? `0${gridHeight.value}` : gridHeight.value; }); window.onload = () => { gridWidth.value = 0; gridHeight.value = 0; };
Your pixel art maker is now ready. If you have any issues while creating this code you can download the source code by clicking on the download button below. Also if you have any queries, suggestions or feedback drop them in the comments below.
Happy Coding!
Hi do you have some ideas how to fix ” cursor: not-allowed; ” during drawing ?? When you finish draw and do not move cursor and than again start drowing suddenly appear “cursor: not-allowed” and than is True maybe ‘stuck’ and drawing is going without mousedown.
Hi do you have some ideas how to fix ” cursor: not-allowed; ” during drawing ?? When you finish draw and do not move cursor and than again start drowing suddenly appear “cursor: not-allowed” and than is True maybe ‘stuck’ and drawing is going without mousedown.
Bro do not shit code pls