본문 바로가기
클론코딩/노마드코더 그림 앱

[클론코딩/그림 앱] 노마드 코더 그림 앱 클론코딩 #1 Drawing

by 기록하는_사람 2022. 10. 25.

CANVAS API

📌 CANVAS API

https://codingrecord2209.tistory.com/254

 

[JavaScript] Canvas API

CANVAS API 📌 CANVAS API : Javascript로 그래픽을 그릴 수 있게 하는 API. https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API element. Among other things, it can be used for animation, game gr..

codingrecord2209.tistory.com

 

Drawing - 클릭 후 드래그하면 선 그려지도록

📌 클릭 후 드래그하면 선 그려지도록

① 마우스가 움직이면, 브러쉬 이동하도록 함. 

② 마우스를 클릭하면, 선을 그리도록 함.

③ 마우스를 클릭 후 떼면, 선을 그리지 않도록 함.

④ 마우스가 캔버스를 벗어나면, 그려지지 않도록 함. 

 

📄 index.html

<!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">
    <title>Meme Maker</title>
    <link rel="stylesheet" href="styles.css" />
</head>
<body>
    <canvas></canvas>

    <script src="app.js"></script>
</body>
</html>

📄 styles.css

canvas {
    width: 800px;
    height: 800px;
    border: 1px solid black;
    border-radius: 5px;
}

body {
    display: flex;
    justify-content: center;
    align-items: center;
}

📄 app.js

const canvas = document.querySelector("canvas")
const ctx = canvas.getContext("2d")

canvas.width = 800;
canvas.height = 800;

ctx.lineWidth = 2;

let isPainting = false;
function onMove(event) {
    if(isPainting) {
        ctx.lineTo(event.offsetX, event.offsetY);
        ctx.stroke();
        return;
    }
    ctx.moveTo(event.offsetX, event.offsetY);
}

function startPaintint() {
    isPainting = true;
}

function cancelPainting() {
    isPainting = false;
}

canvas.addEventListener("mousemove", onMove);
canvas.addEventListener("mousedown", startPaintint);
canvas.addEventListener("mouseup", cancelPainting);
canvas.addEventListener("mouseleave", cancelPainting);

 

Drawing - 선 굵기 설정

📌 선 굵기 설정

 

📄 index.html

...
    <!-- line width -->
    <input id="line-width" type="range" min="1" max="10" vlaue="5" step="0.5" />

    <script src="app.js"></script>
</body>
</html>

📄 app.js

const lineWidth = document.getElementById("line-width");
..
function onLineWidthChange(event) {
    ctx.lineWidth = event.target.value;
}
...
lineWidth.addEventListener("change", onLineWidthChange);

 

Drawing - 색 설정

📌 색 설정

 

📄 index.html

...
    <!-- line width -->
    <input id="line-width" type="range" min="1" max="10" vlaue="5" step="0.5" />

    <!-- color -->
    <input id="color" type="color" />
    <script src="app.js"></script>
</body>
</html>

📄 app.js

const lineWidth = document.getElementById("line-width");
const color = document.getElementById("color");
...
function onColorChange(event) {
    ctx.strokeStyle = event.target.value;
    ctx.fillStyle = event.target.value;
}
...
lineWidth.addEventListener("change", onLineWidthChange);
color.addEventListener("change", onColorChange);

 

Drawing - 색 팔레트 추가

📌 색 팔레트 추가

 

📄 index.html

...
<body>
    <canvas></canvas>

    <!-- line width -->
    <input id="line-width" type="range" min="1" max="10" vlaue="5" step="0.5" />

    <!-- color -->
    <input id="color" type="color" />

    <div
    class="color-option"
    style="background-color: #1abc9c"
    data-color="#1abc9c"
  ></div>
  <div
    class="color-option"
    style="background-color: #3498db"
    data-color="#3498db"
  ></div>
  <div
    class="color-option"
    style="background-color: #34495e"
    data-color="#34495e"
  ></div>
  <div
    class="color-option"
    style="background-color: #27ae60"
    data-color="#27ae60"
  ></div>
  <div
    class="color-option"
    style="background-color: #8e44ad"
    data-color="#8e44ad"
  ></div>
  <div
    class="color-option"
    style="background-color: #f1c40f"
    data-color="#f1c40f"
  ></div>
  <div
    class="color-option"
    style="background-color: #e74c3c"
    data-color="#e74c3c"
  ></div>
  <div
    class="color-option"
    style="background-color: #95a5a6"
    data-color="#95a5a6"
  ></div>
  <div
    class="color-option"
    style="background-color: #d35400"
    data-color="#d35400"
  ></div>
  <div
    class="color-option"
    style="background-color: #bdc3c7"
    data-color="#bdc3c7"
  ></div>
  <div
    class="color-option"
    style="background-color: #2ecc71"
    data-color="#2ecc71"
  ></div>
  <div
    class="color-option"
    style="background-color: #e67e22"
    data-color="#e67e22"
  ></div>

    <script src="app.js"></script>
</body>
</html>

📄 styles.css

canvas {
    width: 800px;
    height: 800px;
    border: 1px solid black;
    border-radius: 5px;
}

body {
    display: flex;
    justify-content: center;
    align-items: center;
}

.color-option {
    width:50px;
    height: 50px;
    cursor: pointer;
}

📄 app.js

const lineWidth = document.getElementById("line-width");
const color = document.getElementById("color");

const colorOptions = Array.from(document.getElementsByClassName("color-option"));
...
function onColorClick(event) {
    const colorValue = event.target.dataset.color;
    ctx.strokeStyle = colorValue;
    ctx.fillStyle = colorValue;
    color.value = colorValue;
 }
...
colorOptions.forEach((color) => color.addEventListener("click", onColorClick));

 

Drawing - 캔버스 채우기 추가

📌 캔버스 채우기  추가

 

📄 index.html

...
    <!-- color fill -->
    <button id="mode-btn">Fill</button>

    <!-- js -->
    <script src="app.js"></script>
</body>
</html>

📄 app.js

...
const modeBtn = document.getElementById("mode-btn");
...
let isPainting = false;
let isFilling = false;
...
function onModeClick() {
    if(isFilling) {
        isFilling = false;
        modeBtn.innerText = "Fill";
    }
    else {
        isFilling = true;
        modeBtn.innerText = "Draw";
    }
}

function onCanvasClick() {
    if(isFilling) {
        ctx.fillRect(0, 0, 800, 800);
    }
}
...
modeBtn.addEventListener("click", onModeClick);

 

Drawing - reset, 지우기 추가

📌 reset, 지우기  추가

 

📄 index.html

...
    <!-- reset -->
    <button id="destroy-btn">Destroy</button>

    <!-- eraser -->
    <button id="eraser-btn">Eraser</button>

    <!-- js -->
    <script src="app.js"></script>
</body>
</html>

📄 app.js

...
const modeBtn = document.getElementById("mode-btn");
const destroyBtn = document.getElementById("destroy-btn");
const eraserBtn = document.getElementById("eraser-btn");

const canvas = document.querySelector("canvas")
const ctx = canvas.getContext("2d")

const CANVAS_WIDTH = 800;
const CANVAS_HEIGHT = 800;
canvas.width = CANVAS_WIDTH;
canvas.height = CANVAS_HEIGHT;

ctx.lineWidth = lineWidth.value;

let isPainting = false;
let isFilling = false;
...
function onDestroyClick() {
    ctx.fillStyle = "white";
    ctx.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
}

function onEraserClick() {
    ctx.strokeStyle = "white";
    isFilling = false;
    modeBtn.innerText = "Fill";
}
...
modeBtn.addEventListener("click", onModeClick);
destroyBtn.addEventListener("click", onDestroyClick);
eraserBtn.addEventListener("click", onEraserClick);

댓글