오늘부터 5인 이상 집합 금지 명령이 적용되는데.. 참 난리도 아닙니다 😔
어서 코로나가 잠잠해졌으면 좋겠어요.
오늘은 7번째 시간이에요! Day 08 project 는 그림판! 을 만드는 과제였습니다. 쓱싹! 그림판을 만들어보자구요 😄
캔버스에 그림판을 만든다. 그리는 선의 색은 시간이 지날수록 무지개처럼 색이 변하며, 그 선의 두께는 두꺼워지다 얇아지다를 반복한다.
먼저 이번 프로젝트는 정답 코드에 대해서만 정리를 해볼게요. 그림판 만드는 기능을 그렇게 빈도수 있게 하지는 않을 것 같아서, 정리만 해놓는 것이 의미가 있을것 같네요..!
<body>
<canvas id="draw" width="800" height="800"></canvas>
<script src="src/index.js"></script>
<style>
html, body {
margin: 0;
}
</style>
</body>
먼저 뼈대인 HTML
은 이렇게 생겼습니다. 간단해요. canvas
태그가 있고, 그 id
는 draw
입니다.
이 친구를 잡아서 작업이 시작될거에요.
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;
초기 설정입니다! draw
를 id
로 가지는 태그를 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
로 만듭니다. 또한, 클릭을 하고 있는 동안에는 마지막 좌표를 저장하는 lastX
와 lastY
에 클릭이 일어난 좌표를 저장해야합니다.
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
으로 증가할건지, 감소할건지 판단합니다.
이렇게 그림을 그려볼 수 있는 그림판을 만들어봤어요!
색이 지 맘대로 변하고 선의 굵기도 난리가 나서 얼마나 유용할진 모르겠지만, 이번시간에 정리한 개념을 기반으로 다르게 설정해서 그림을 효율적으로 그릴 수 있지 않을까, 생각이 듭니다.
그림 그리는 포켓몬이래요. 졸귀네요
틀린내용이나 수정할 내용이 있다면 언제든지 피드백 부탁드립니다!
감사합니다!🤗