[JS] 🗓️JavaScript 30 - Day 8

📖Day 8 - Fun with HTML5 Canvas
JavaScript 30의 Day 8 프로젝트는 HTML의 canvas element와 다양한 메서드를 사용하여 낙서해보는 프로젝트이다.
🤓📄코드 모아보기
HTML
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>HTML5 Canvas</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <canvas id="draw" width="800" height="800"></canvas>
    <span class="mode">🖌️ ARTIST MODE</span>
    <script src="main.js"></script>
  </body>
</html>CSS
html,
body {
  margin: 0;
  height: 100vh;
}
body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background: linear-gradient(
    270deg,
    #f0e9d2 0%,
    #e6ddc4 33%,
    #678983 66%,
    #181d31 100%
  );
}
#draw {
  background-color: white;
}
.mode {
  margin-top: 5%;
  font-size: 2rem;
  font-weight: 700;
  font-style: italic;
  text-decoration: underline;
  color: #7b113a;
  font-family: sans-serif;
}JavaScript
const canvas = document.querySelector("#draw");
const ctx = canvas.getContext("2d");
canvas.width = window.innerWidth * 0.8;
canvas.height = window.innerHeight * 0.8;
ctx.strokeStyle = "#BADA55";
ctx.lineJoin = "round";
ctx.lineCap = "round";
ctx.lineWidth = 50;
// ctx.globalCompositeOperation = "multiply";
let isDrawing = false;
let lastX = 0;
let lastY = 0;
let hue = 0;
let direction = true;
let eraseMode = false;
function draw(e) {
  if (!isDrawing) return;
  if (eraseMode) {
    drawEraseMode(e);
  } else {
    ctx.strokeStyle = `hsl(${hue}, 100%, 50%)`;
    ctx.beginPath();
    // start from
    ctx.moveTo(lastX, lastY);
    // go to
    ctx.lineTo(e.offsetX, e.offsetY);
    ctx.stroke();
    [lastX, lastY] = [e.offsetX, e.offsetY];
    hue++;
    if (hue >= 360) {
      hue = 0;
    }
    ctx.linewidth++;
    if (ctx.lineWidth >= 80 || ctx.lineWidth <= 1) {
      direction = !direction;
    }
    if (direction) {
      ctx.lineWidth++;
    } else {
      ctx.lineWidth--;
    }
  }
}
function drawEraseMode(e) {
  ctx.strokeStyle = "white";
  ctx.lineWidth = 50;
  ctx.beginPath();
  ctx.moveTo(lastX, lastY);
  ctx.lineTo(e.offsetX, e.offsetY);
  ctx.stroke();
  [lastX, lastY] = [e.offsetX, e.offsetY];
}
canvas.addEventListener("mousedown", (e) => {
  isDrawing = true;
  [lastX, lastY] = [e.offsetX, e.offsetY];
});
canvas.addEventListener("mousemove", draw);
canvas.addEventListener("mouseup", () => (isDrawing = false));
canvas.addEventListener("mouseout", () => (isDrawing = false));
window.addEventListener("keydown", (e) => {
  if (e.key === "e") {
    eraseMode = !eraseMode;
    if (eraseMode) document.querySelector(".mode").innerHTML = `⚪ ERASER MODE`;
    else document.querySelector(".mode").innerHTML = `🖌️ ARTIST MODE`;
  }
});🔎코드 설명
- 가장 먼저, 
querySelector를 사용하여 draw라는 id를 가진 canvas element를 canvas에 할당해준다. 그 후에,getContext메서드를 활용해 캔버스의 드로잉 컨텍스트(그려질 대상)을 ctx라는 변수에 받아준다. 이번 프로젝트에는 2d 그림판을 구현하기 때문에 인자로는 '2d'를 넣어준다. 이제 canvas의 넢이와 너비를 window의 높이와 너비로 바꿔주고, ctx의strokeStyle,lineJoin,lineCap,lineWidth를 설정해준다. - 이제 
draw함수를 만들어준다. 이 함수는 마우스가 움직일 때 실행되어야 하므로 addEventListener의mousemove이벤트를 이용한다.draw함수를 완성시키기 위해서 ctx의beginPath메서드를 통해 새로운 경로를 생성하고moveTo메서드로 x와 y의 좌표를 옮겨준다. 좌표를 옮겼으면lineTo메서드를 활용해 선의 마지막 지점을 설정하는데 이 때 MouseEvenet의offsetX,offsetY를 통해 현재 마우스의 좌표를 받아준다. 마지막으로stroke메서드로 선을 그려준다. 정리하면 다음과 같다.ctx.beginPath(); // 새로운 경로 생성 ctx.moveTo(lastX, lastY); // 선의 시작점 ctx.lineTo(e.offsetX, e.offsetY); // 선의 종착점 ctx.stroke(); // 선 긋기 - 처음에 lastX와 lastY를 0으로 설정했기 때문에 한 점에서 선이 그어지는 걸 바꾸기 위해서 선을 그린 후에는 
lastX -> e.offsetX,lastY -> e.offsetY로 바꿔준다. 마우스를 클릭한 상태여야만 그림이 그려져야 하기 때문에 isDrawing 이라는 변수를 만들어주고, draw 함수가 실행되기 전에 isDrawing이 false라면 바로 return 하여 더 이상 함수가 실행되지 않도록 한다. 이후에mouseup과mouseout이벤트가 발생하면 isDrawing을 false로 바꿔준다. 이후에는 디자인을 바꿔주기 위한 코드이다. - 다른 블로그를 참고해보니 
지우개 모드를 만들어준 것을 봤다. 강의 외에 추가적인 기능을 만들어보는 것이 이 프로젝트의 묘미라고 생각해 나도 만들어보았다. 기본적으로 ARTIST MODE에서 키보드e를 누르면 ERASER MODE로 바뀌게 했는데, 따로 drawEraseMode라는 함수를 만들어 50의 두께로 흰색으로 칠하여 지우개 효과를 보여줄 수 있었다. 
🚀TIL(Today I Learned)
- 강의 외에 추가적으로 내가 구현하고 싶은 부분을 구현하다보니 더 재미있는 프로젝트였다. 완성작은 허접하지만 그만큼 발전해야할 필요성을 느낄 수 있었다!!
 canvas(HTML, JavaScript),HTMLCanvasElement.getContext(),다양한 메서드들
'Language > JavaScript' 카테고리의 다른 글
| [JS] 🗓️JavaScript 30 - Day 10 (0) | 2021.11.26 | 
|---|---|
| [JS] 🗓️JavaScript 30 - Day 9 (0) | 2021.11.23 | 
| [JS] 🗓️JavaScript 30 - Day 7 (0) | 2021.11.21 | 
| [JS] 🗓️JavaScript 30 - Day 6 (0) | 2021.11.19 | 
| [JS] 🗓️JavaScript 30 - Day 5 (0) | 2021.11.18 | 
댓글
이 글 공유하기
다른 글
- 
[JS] 🗓️JavaScript 30 - Day 10
[JS] 🗓️JavaScript 30 - Day 10
2021.11.26 - 
[JS] 🗓️JavaScript 30 - Day 9
[JS] 🗓️JavaScript 30 - Day 9
2021.11.23 - 
[JS] 🗓️JavaScript 30 - Day 7
[JS] 🗓️JavaScript 30 - Day 7
2021.11.21 - 
[JS] 🗓️JavaScript 30 - Day 6
[JS] 🗓️JavaScript 30 - Day 6
2021.11.19