e-d-i
e-d-i

Reputation: 39

How to draw via mouse-click without using the canvas-element

I am trying to create an "Etch-A-Sketch"-program, which should let the user draw only by clicking or holding the mouse-button. How can I realize that in JavaScript?

Somehow after the user chooses a color via clicking on the color-button, the color is already drawn as soon as the mouse cursor enters the drawing area (div class="container").

I've tried several functions, but it's still not working as expected... Could someone please provide a hint?

"use strict";

const divContainer = document.querySelector(".container");
const btnsContainer = document.querySelector(".buttons");
const btnBlack = document.createElement("button");
const btnGreyScale = document.createElement("button");
const btnRgb = document.createElement("button");
const btnErase = document.createElement("button");
const btnShake = document.createElement("button");

function createGrid(col, rows) {
  for(let i = 0; i < (col * rows); i++) {
      const div = document.createElement("div"); 
      divContainer.style.gridTemplateColumns = `repeat(${col}, 1fr)`;
      divContainer.style.gridTemplateRows = `repeat(${rows}, 1fr)`;
      divContainer.appendChild(div).classList.add("box");
  }
}
createGrid(16,16)

let isDrawing = false;
window.addEventListener("mousedown", () => {
    isDrawing = true;
});
window.addEventListener("mouseup", () => {
    isDrawing = false;
});

function paintBlack() { 
  const boxes = divContainer.querySelectorAll(".box");
  btnBlack.textContent = "Black";
  btnBlack.addEventListener("click", function () {
    boxes.forEach(box => box.addEventListener("mouseover", function () {
      this.style.background = "#000";
    }))
  })
  btnsContainer.appendChild(btnBlack).classList.add("btn");
}
paintBlack();

function paintGreyScale() { 
  const boxes = divContainer.querySelectorAll(".box");
  btnGreyScale.textContent = "Grey";
  btnGreyScale.addEventListener("click", function () {
    boxes.forEach(box => box.addEventListener("mouseover", function () {
      let randNum = Math.floor(Math.random() * 256);
      let grayScale = `rgb(${randNum},${randNum},${randNum})`;
      box.style.background = grayScale;
    }))
  })
  btnsContainer.appendChild(btnGreyScale).classList.add("btn");
}
paintGreyScale();

function paintRgb() { 
  const boxes = divContainer.querySelectorAll(".box");
  btnRgb.textContent = "Rainbow";
  btnRgb.addEventListener("click", function () {
    boxes.forEach(box => box.addEventListener("mouseover", function () {
      let r = Math.floor(Math.random() * 256);
      let g = Math.floor(Math.random() * 256);
      let b = Math.floor(Math.random() * 256);
      const rgb = `rgb(${r},${g},${b})`;
      box.style.background = rgb;
    }))
  })
  btnsContainer.appendChild(btnRgb).classList.add("btn");
}
paintRgb();

function erase() { 
  const boxes = divContainer.querySelectorAll(".box");
  btnErase.textContent = "Erase";
  btnErase.addEventListener("click", function () {
    boxes.forEach(box => box.addEventListener("mouseover", function () {
      this.style.background = "#FFF";
    }))
  })
  btnsContainer.appendChild(btnErase).classList.add("btn");
}
erase();

function clearCanvas() { 
  const boxes = divContainer.querySelectorAll(".box");
  btnShake.textContent = "Shake it!";
  btnShake.addEventListener("click", function () {
    boxes.forEach(box => box.style.backgroundColor = "#FFF");
  })
  btnsContainer.appendChild(btnShake).classList.add("shake");
}
clearCanvas();

btnShake.addEventListener("click", clearCanvas);
*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
}

html {
  font-size: 16px;
}

body {
  background: linear-gradient(to bottom, #1488CC, #2B32B2);
  color: #FFF;
  line-height: 1.5;
  height: 100vh;
}

#wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  text-align: center;
}

.container {
  width: 500px;
  height: 500px;
  display: grid;
  background-color: #FFF;
  box-shadow: 0 0 10px;
}

.box {
  border: .5px solid #808080;
}

.shake {
  animation: shake .5s linear 1;
}

@keyframes shake {
  10%,
  90% {
    transform: translate3d(-1px, 0, 0);
  }
  20%,
  80% {
    transform: translate3d(2px, 0, 0);
  }
  30%,
  50%,
  70% {
    transform: translate3d(-4px, 0, 0);
  }
  40%,
  60% {
    transform: translate3d(4px, 0, 0);
  }
}
<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
    <title>Etch-A-Sketch</title>
  </head>

  <body>

    <div id="wrapper">
      <main>
        <div class="container"></div>
        <div class="buttons"></div>
      </main>
    </div>

    <script src="etchAsketch.js"></script>

  </body>

</html>

Upvotes: 0

Views: 674

Answers (1)

Joseph Balnt
Joseph Balnt

Reputation: 140

The mousedown event

window.addEventListener("mousedown", () => {
    isDrawing = true;
});

sets isDrawing to true, and mouseup event to false, but you never use this variable to check whether the color should be drawn.

Solution: for each statement you have that's setting the background color of a square (except for clearCanvas), wrap it in an if statement checking if the user isDrawing:

if (isDrawing){this.style.background = "#000";} //black
if (isDrawing){this.style.background = grayScale;} //gray
if (isDrawing){this.style.background = rgb;} // rainbow
if (isDrawing){this.style.background = "#FFF";} // erase

boxes.forEach(box => box.style.backgroundColor = "#FFF");
  })  //leave clearCanvas as it is

Upvotes: 1

Related Questions