비전공자 개발일기

Pixel Art Maker 본문

Javascript

Pixel Art Maker

HiroDaegu 2022. 12. 25. 01:08
728x90
SMALL

grid를 활용한 그림 그리기

 

실제 영상
<html lang="ko">

<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" />
    <!-- Script -->
    <script defer src="main.js"></script>
</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>

</body>

</html>
* {
    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;
    }
  }
//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;
};
728x90
LIST

'Javascript' 카테고리의 다른 글

Product Image Zoom  (0) 2022.12.28
Decimal - Binary Converter  (0) 2022.12.27
Emoji Cursor Trail Effect  (0) 2022.12.24
Quiz App new Version  (0) 2022.12.23
Number Trivia  (0) 2022.12.20