Implement Pixel Art grid using HTML, CSS and JavaScript | The DOM Challenge

Implement Pixel Art grid using HTML, CSS and JavaScript | The DOM Challenge

This is the second challenge from The DOM Challenge series created by Sunny Puri (SDE2 at Swiggy) and Sadanand Pai (SDE2 at CoinDCX) to inspire and motivate developers to get more proficient in DOM manipulation and learn JavaScript applications.

Challenge 2: Pixel Art Grid

This is the second challenge from The DOM Challenge series, creating a pixel art grid using HTML, CSS, and JavaScript. For this challenge you would be provided with a simple template and using it you have to solve the challenge.

Note:- You can modify the code according to your style and convenience but make sure you follow all the rules.

Templates

For HTML,

<body>
    <div id="grid"></div>

    <script src="script.js"></script>
    <script>
        new PixelArt("#grid", 10, 10);
    </script>
</body>

For Js,

/*
 * Creates pixel art grid
 * @param el DOM Element
 * @param rows Number of rows
 * @param rows Number of cols
 */
function PixelArt(el, rows, cols) {
    // write logic to create pixel art grid.
}

Also read, Learning to Think Like a Computer

Rules

There are a few rules by which your pixel art grid should abide,

  • You can create a grid of any size of your choice.
  •  Whenever you reload the app, a new set of colors should appear at the bottom row of the grid.
  • When you select any color from the bottom row and click on an empty grid box, that particular box should get filled with the selected color.
  • and if you select any other color and then click on the box which is already filled with color, then the color of the box should get replaced with the active color.

Demo

Also read, Easy tutorial to build React Autosuggest from scratch

My Solution

My approach to this problem is straightforward, first I will create a grid of 10 rows and 7 columns through Js, for this, I will place a div and add id ‘grid’ in it.

HTML

<body>
    <h1>Pixel Art</h1>
    <div id="grid"></div>
    <script src="script.js"></script>
</body>

CSS

Then I have added some CSS to display the grid according to the given columns and rows,

body {
  text-align: center;
  background-color: #f2f2f2;
}

#grid {
  width: 25em;
  height: 35em;
  margin: 0 auto;
  padding: 5px;
  background-color: white;
  border: 2px solid #2c3e50;
  border-radius: 5px;
  display: grid;
  grid-template: repeat(8, 1fr) / repeat(7, 1fr);
  gap: 1px;
}

.box {
  height: 50px;
  width: 50px;
  border: 1px solid #2c3e50;
  border-radius: 2px;
}

.box:hover{
  cursor: pointer;
}

JS

Instead of manually adding boxes to the grid, I will take the help of javascript to add a total of 70 boxes and with the help of CSS, I will align these boxes in the grid. At first, I am using a document.getElementById('grid') method to get the reference of the grid div.

Then I will create and call the makingGrid(gridNumber) function and will pass the number of boxes I need, in makingGrid(gridNumber)function first we create a new fragment with the help of document.createDocumentFragment(), document.createDocumentFragment() creates a new empty DocumentFragment into which DOM nodes can be added to build an offscreen DOM tree.

Then we will create a div with the help of document.createElement(), document.createElement() method creates the HTML element specified by tagName, or an HTMLUnknownElement if tagName isn’t recognized.

And then I will also add class box and also add box number to identification and finally add it to fragment and then to grid.

let grid = document.getElementById('grid');
let currentColor;

function makingGrid(gridNumber) {
  const fragment = document.createDocumentFragment();
  for (let i = 1; i <= gridNumber; i++) {
    const iElem = document.createElement('div');
    iElem.classList.add('box');
    iElem.dataset.boxNumber = i;
    fragment.appendChild(iElem);
  }
  grid.appendChild(fragment);
}

makingGrid(70);

After creating the grid, inside the makingGrid(gridNumber) function, At first get the reference of the box div using document.querySelectorAll('.box'), which returns the array object. With the help of forEach the array method, I attach ‘click’ addEventListener to each box’s div and when the user will click on any box, then the event is triggered and getBoxes the function is called in which I passed the event, box reference, and total box number.

And also I am also filling the background color of the last seven boxes with random colors with the help of generateRandomColor() function so that users can select colors to fill empty color boxes.

let boxes = document.querySelectorAll('.box');
boxes.forEach((box, index) => {
  box.addEventListener('click', (e) => getBoxes(e, box, boxes.length));
  if (index >= boxes.length - 7) {
    box.style.backgroundColor = generateRandomColor();
  }
});

In generateRandomColor() function with the help of Math.random function we will return a random hexadecimal color value.

In CSS, one of the ways to represent colors is in hexadecimal values, #RRGGBB . The value of hexadecimal ranges from 00 to FF. So in CSS, #000000 represents black and #FFFFFF represents white and the combination of any number in the limit of these offsets produces different colors.

First, we save the maximum value of hexadecimal with 0x in front of it in the variable maxVal, In JavaScript, we add 0x before a hexadecimal number. Then multiply it with Math.random to generate a floating-point random number.

After that, we will first convert the floating-point number to an integer and then to that integer into hexadecimal again using the toString(16) method, but there may be also the chance that returning number can be less than 6 digits, so in order to solve it, we will use padStart(6, 0) method to fill the empty space with 0 in starting positions if the number’s digit is less than 6.

function generateRandomColor() {
  let maxVal = 0xffffff; // 16777215
  let randomNumber = Math.random() * maxVal;
  randomNumber = Math.floor(randomNumber);
  randomNumber = randomNumber.toString(16);
  let randColor = randomNumber.padStart(6, 0);
  return `#${randColor.toUpperCase()}`;
}

Finally, In getBoxes function, first we identify the box number through the dataset, then check if users click on any box, first it checks if the box number is less than the last 7 boxes (70-7), and then if any color has already been chosen then it fills the background of that particular boxes if not then it consoles users that there is ‘no color is active’.

But if the user clicks on the box whose number lies between the last 7 boxes (70-7) then it will pick the current color code and save it to the variable currentColor.

function getBoxes(e, box, size) {
  let boxNumber = e.target.dataset.boxNumber;
  if (boxNumber < size - 7) {
    if (currentColor) {
      box.style.backgroundColor = currentColor;
    } else {
      console.log('no colour is active');
    }
  } else {
    currentColor = box.style.backgroundColor;
    console.log('New Background added', currentColor);
  }
}

Also read, Implement Star Rating Widget using HTML, CSS and JavaScript | The DOM Challenge

Demo