Javascript_30_08

Derek·2020년 12월 23일
1

javascript_30

목록 보기
9/31
post-thumbnail

안녕하세요!

Derek입니다. 😃

오늘부터 5인 이상 집합 금지 명령이 적용되는데.. 참 난리도 아닙니다 😔
어서 코로나가 잠잠해졌으면 좋겠어요.

오늘은 7번째 시간이에요! Day 08 project 는 그림판! 을 만드는 과제였습니다. 쓱싹! 그림판을 만들어보자구요 😄




08. Fun with HTML5 Canvas

목표

캔버스에 그림판을 만든다. 그리는 선의 색은 시간이 지날수록 무지개처럼 색이 변하며, 그 선의 두께는 두꺼워지다 얇아지다를 반복한다.

먼저 이번 프로젝트는 정답 코드에 대해서만 정리를 해볼게요. 그림판 만드는 기능을 그렇게 빈도수 있게 하지는 않을 것 같아서, 정리만 해놓는 것이 의미가 있을것 같네요..!




Derek과 Web Bos 구현코드

<body>
  <canvas id="draw" width="800" height="800"></canvas>
  <script src="src/index.js"></script>
<style>
  html, body {
    margin: 0;
  }
</style>
</body>

먼저 뼈대인 HTML 은 이렇게 생겼습니다. 간단해요. canvas 태그가 있고, 그 iddraw 입니다.
이 친구를 잡아서 작업이 시작될거에요.

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

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

ctx.strokeStyle = "#BADA55";
ctx.lineJoin = "round";
ctx.lineCap = "round";
ctx.lineWidth = 50;

초기 설정입니다! drawid 로 가지는 태그를 canvas 에 담아두고, 그 친구를 대상으로 getContext 함수를 호출합니다. getContext의 정의는 다음과 같아요.

HTMLCanvasElement.getContext() 메소드는 캔버스의 드로잉 컨텍스트를 반환합니다. 컨텍스트 식별자가 지원되지 않을 경우 null을 반환합니다.

음.. 뭔가 팽! 이해가 되진 않지만, 그림판을 만들기 위해서는 꼭 필요한 객체라고 보시면 될 것 같습니다 :)

그 후에는 canvas.width = window.innerWidth;, canvas.height = window.innerHeight; 를 통해 캔버스의 가로와 세로의 길이를 정해줘요.

다음부터 나오는 4줄에 대해서 간단하게 정리하면,

  • strokeStyle : 윤곽선 (그리는 선) 에 대한 색을 지정합니다.
  • lineJoin : 그림을 그릴 때, 꺾는 지점이 둥글둥글할지, 뾰족할지, 정해줘요. MDN를 확인해보세요.
  • lineCap : 그리는 선의 시작과 끝이 둥글둥글할지, 평평할지 정해줍니다. MDN자료에 그림으로 나와있어요.
  • lineWidth : 유추가능하듯이, 그리는 선의 굵기입니다.


    또한, 이번 프로젝트에는 몇 가지 변수가 있습니다.
let isDrawing = false;

let lastX = 0;
let lastY = 0;

let direction = true;

let hue = 0;
  • isDrawing : 이벤트 처리를 위해서, 마우스가 캔버스를 나간다거나 / 클릭이 해제된다거나, 할 때 조정해주는 flag입니다.
  • lastX, lastY : 그림을 그릴 때, 그림이 끝난 부분의 좌표를 저장합니다. 클릭을 해제한 마우스가 다른곳으로 옮겨가 새로운 그림을 작업할때, 이 변수는 새로운 지점을 계속 저장하게 됩니다.
  • direction : 선의 굵기를 변화시키기 위해서 필요한 flag입니다.
  • hue : 색을 변화시키기 위해서 필요한 flag입니다

본격적으로 시작해보겠습니다. 먼저 필요한 eventListener부터 정리해볼게요.

canvas.addEventListener("mousemove", draw);
canvas.addEventListener("mousedown", (event) => {
    isDrawing = true;
    lastX = event.offsetX;
    lastY = event.offsetY;
});
canvas.addEventListener("mouseup", () => isDrawing = false);
canvas.addEventListener("mouseout", () => isDrawing = false); 

먼저 mousemove 이벤트는, 캔버스 위에 마우스가 움직일때 draw 함수를 실행합니다. 물론, 해당 함수에는 isDrawing 변수로 마우스를 클릭한 채 움직이는지, 클릭하지 않은채로 움직하는지 구분하여 실행시킵니다.

mousedown 이벤트는 클릭이 발생하면, flag인 isDrawing 변수를 ture로 만듭니다. 또한, 클릭을 하고 있는 동안에는 마지막 좌표를 저장하는 lastXlastY 에 클릭이 일어난 좌표를 저장해야합니다.

mouseup, mouseout 이벤트는 간단합니다. 각각 캔버스 위에서 클릭이 해제되거나 캔버스 밖으로 나간다면, isDarwing 변수를 false 로 만듭니다.


그럼 이제 가장 핵심인 draw 함수를 살펴보겠습니다.

function draw(event){
    if(!isDrawing) return; // stop the function if it is not the drawing mode.

    ctx.strokeStyle = `hsl(${hue}, 100%, 50%)`;

    ctx.beginPath();
    ctx.moveTo(lastX, lastY);
    ctx.lineTo(event.offsetX, event.offsetY);
    ctx.stroke();
    lastX = event.offsetX;
    lastY = event.offsetY;
    
    hue++;
    if(hue >= 360){
        hue = 0;
    }

    if(ctx.lineWidth >= 100 || ctx.lineWidth <= 1){
        direction = !direction;
    }
    if(direction){
        ctx.lineWidth++;
    }
    else{
        ctx.lineWidth--;
    }
}

이제 그림을 그립니다. 첫 번째 줄에서 flag를 활용하는 모습을 확인하실 수 있어요.

hsl 함수를 설명하기 전에, 큰 뭉탱이를 먼저 설명드리면,

beginPath (나 이제 그림그릴거야!) -> moveTo (마지막으로 그림 끝난부분으로 일단 가서,) -> lineTo (새롭게 그린 부분으로 그림 그릴거야!) -> stroke (ㄹㅇ로 그려!)

이런식으로 진행됩니다. 하나하나 함수의 원형 / 쓰이는 용도 / 정의를 설명하기는.. 불필요한 것 같아요. 귀찮아요.

이렇게 그림은 일단 어찌저찌 그리게되었습니다. 그렇다면 남은 부분은, 색 변하게 하기, 선 굵어졌다 얇아졌다 해주기.

색 변하게 해주기

이 기능은 hue 라는 변수를 사용해요.

ctx.strokeStyle = `hsl(${hue}, 100%, 50%)`;
hue++;
    if(hue >= 360){
        hue = 0;
    }

그림을 그리면서 hue 변수는 계속 증가하다가, 360이 넘으면 0으로 초기화 되고 다시 증가합니다.

100%, 50% 한 곳은 각각 s (채도), l (명도) 부분입니다. 이는 고정으로, h (색) 만을 조정해요. h 값이 0부터 360까지 분포되는데, 이는 띠 모양이라, 색이 돌고도는 형식으로 보입니다. 0은 빨강이고... 증가하며 변하다가 360에 도달할수록 다시 빨강색.. 그러다가 다시 0으로 초기화시켜서 다시 반복시킵니다.


선의 굵기는 다음 코드에서 조정을 해줘요.

if(ctx.lineWidth >= 100 || ctx.lineWidth <= 1){
        direction = !direction;
    }
    if(direction){
        ctx.lineWidth++;
    }
    else{
        ctx.lineWidth--;
    }

ctx.lineWidth 의 값을 1부터 100까지 조정하는데, flag값인 direction 으로 증가할건지, 감소할건지 판단합니다.




이렇게 그림을 그려볼 수 있는 그림판을 만들어봤어요!

색이 지 맘대로 변하고 선의 굵기도 난리가 나서 얼마나 유용할진 모르겠지만, 이번시간에 정리한 개념을 기반으로 다르게 설정해서 그림을 효율적으로 그릴 수 있지 않을까, 생각이 듭니다.
그림 그리는 포켓몬이래요. 졸귀네요

틀린내용이나 수정할 내용이 있다면 언제든지 피드백 부탁드립니다!
감사합니다!🤗

profile
Whereof one cannot speak, thereof one must be silent.

0개의 댓글