기본 적인 html, css를 공부하는데 예제로 그림판이 나와서 직접 만들어 볼겁니다.
제가 만들면서 작성을 하고 있음으로, 사족이 많고, 제가 해본 코드들이 다~~~정리될 것으로 예상됩니다.
<a> 태그에 대해 공부를 하고 있었죠. 근데 아래쪽에 다운로드 관련한 설명의 예시로 그림판이 나오는 것입니다. 그리고 노마드 코더에서도 그림판을 만드는 예시가 있던걸 알고 있어서, 직접 영상을 보지않고, 만들어진걸 찾아보지 않고 만들어 보자! 라는 생각이 들었습니다.
참고하는 예시는 오직 https://developer.mozilla.org/ko/docs/Web/HTML/Element/a 이 사이트 에서만 참고를 하였습니다.
새로운 프로젝트를 만들고 예시에 나와있는 스크립트를 가져다가한번 실험을 해보았고 점차 제가 만들고 싶은 기능을 추가 하려고합니다.
html 파일을 준비 했습니다.
<!document html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>
그림판 만들어보기
</title>
<link href="./assets/images/title-icon.png" rel="shortcut icon" type="image/x-icon">
</head>
<body>
<canvas width="500" height="500"></canvas>
</body>
</html>
제가 만들었다는 느낌을 내기위해 파비콘을 추가해줬습니다. 이미지로는 제 블로그의 프로필 사진으로 하였습니다.
이 프로젝트는 이제 제껍니다
<canvas / >
처음엔 조금 깔끔하게 만들어 보겠다고 이렇게 했다가 안되는 걸 알았습니다.
ㅎㅎ canvas는 닫는 태그가 필수요소라고 하니 저와같은 실수를 하지 않길바랍니다.
저만 몰랐던거 아니라고 해주세요 제발
이제 저는 여기서 뭘 해야할까란 의문이 들기 시작합니다.
예제를 살짝 컨닝해서 캔버스에서 마우스의 움직임에 따라 작동 해야하니까 mousemove 이벤트를 생성해 줬습니다.
근데 css를 설정을 안해줬더니.. 어디가 캔버스인지를 모르겠는겁니다.. 그래서 급하게 css 설정을 해줬습니다.

그럼 마우스가 움직일때마다 감지는 되고, 이제 그림을 그려봐야겠죠?!
getContext를 2d로 설정해 줬습니다. 저는 2d렌더링이 필요한 것이니까요!
getContext메소드는 캔버스의 드로잉 컨텍스트를 반환 한다고 합니다. 드로잉 컨텍스트가 뭔지 모르시는분 계신가요?
부끄러워 마세요. 나름 1년간 개발을 했고 학부생때 배웠긴 하지만 저도 모르니깐요. 모르면 검색해서 알면 된다고 생각합니다.
컨텍스트(context)는 사전적 정의로는 문맥이라는 뜻이 있더라구요. 자바 스크립트에서는 실행에 필요한 다양한 정보를 형상화하고, 이들을 목록화 관리하기 위한 추상적인 개념 이라고 정리가 되어있더라구요.
저는 여기서 간단하게, 이해하고 넘어갔습니다. 아마 제대로 다시 공부해서 블로그에 정리하지 않을까 싶네요! 모르는 용어를 정리해 두고 하나하나 꼼꼼하게 공부하면 진도가 늦어지니 넘어갔습니다.
https://developer.mozilla.org/ko/docs/Web/API/HTMLCanvasElement/getContext
HTMLCanvasElement.getContext() - Web API | MDN
HTMLCanvasElement.getContext() 메소드는 캔버스의 드로잉 컨텍스트를 반환합니다. 컨텍스트 식별자가 지원되지 않을 경우 null을 반환합니다.
developer.mozilla.org
예제는 마우스이벤트가 다 그려져있지만 저는 어떻게 동작하는 건지 궁금했습니다.
그래서 beginPath()에대해서 찾아봤고, 다른 예제 사이트를 발견하여 그사이트에 있는 스크립트를 사용 해봤습니다.
<script>
let canvas = document.getElementById('canvas')
let brush = canvas.getContext("2d");
brush.beginPath();
brush.lineWidth = "5";
brush.strokeStyle = "green";
brush.moveTo(0, 75);
brush.lineTo(250, 75);
brush.stroke();
canvas.addEventListener('mousemove', event => console.log(event))
</script>
beginPath() : 경로를 시작하거나 현재 경로를 재설정
lineWidth : 좌표 공간 단위로 선 너비를 지정하는 숫자
저는 lineWidth라고 해서 당연히 가로의 길이겠지 했는데 선의 너비 였습니다.. 두둥
strokeStyle : 선의 스타일
moveTo() : 지정된 지점에서 새 하위 경로
lineTo(): 하위 경로의 마지막 지점을 지정된 좌표 lineTo()에 연결하여 현재 하위 경로에 직선 추가
stroke() : 현재 스트로크 스타일로 현재 또는 지정된 경로를 선으로 표시합니다.
canvas에 대한 메소드들은 https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/canvas 이곳에 잘 정리 되어있습니다.
그럼이제 마우스가 움직일때 마다 선이 그려져야하니 mousemove를 사용할떄가 된 것 같습니다.
제가 콘솔로 표시하게끔 해놨으니 콘솔을 볼까요.
허허 네 뭐가 뭔지 제가 필요한 정보가 어떤것인지 잘 모르겠죠? 역시 검색을 합니다.
https://developer.mozilla.org/en-US/docs/Web/API/Element/mousemove_event
Element: mousemove event - Web APIs | MDN
The mousemove event is fired at an element when a pointing device (usually a mouse) is moved while the cursor's hotspot is inside it.
developer.mozilla.org
너무 잘 정리가 되어있네요. 제가 사용해야하는 정보는 offsetX, offsetY 입니다.
<script>
let canvas = document.getElementById('canvas')
let brush = canvas.getContext("2d");
function draw(x,y){
brush.beginPath();
brush.lineWidth = "5";
brush.strokeStyle = "green";
brush.moveTo(0, 75);
brush.lineTo(x, y);
brush.stroke();
}
canvas.addEventListener('mousemove', event => draw(event.offsetX, event.offsetY) )
</script>
draw란 메소드를 만들고, mouse가 움직일때 실행해 줬습니다.
결과는!
마우스 포인트에따라 움직이긴 하지만 moveTo()가 고정이 되어있으니 그곳에서부터 선이 생기고 있습니다.
그럼 moveTo도 변경해 줘야 할 것 같습니다.
<script>
let canvas = document.getElementById('canvas');
let brush = canvas.getContext("2d");
function draw(mouseX, mouseY, pastMouseX,pastMouseY){
brush.beginPath();
brush.lineWidth = "1";
brush.strokeStyle = "green";
brush.moveTo(pastMouseX, pastMouseY);
brush.lineTo(mouseX, mouseY);
brush.stroke();
}
canvas.addEventListener('mousemove', event => {
console.log(event)
draw(event.offsetX, event.offsetY, event.pageX, event.pageY)} )
</script>
이렇게하니 시작점이 고정이 안되서 그림이 그려지는 것 같긴 하지만 점으로 표현되는 것이 아닌 선으로 표현이 되고있죠?
좌표의 차이가 존재한다는 것 이기때문에 수정해줘야 할 것 같습니다.
<script>
let canvas = document.getElementById('canvas');
let brush = canvas.getContext("2d");
let pastMouseX = 0
let pastMouseY = 0
function draw(mouseX, mouseY){
brush.beginPath();
brush.lineWidth = "1";
brush.strokeStyle = "green";
brush.moveTo(pastMouseX, pastMouseY);
brush.lineTo(mouseX, mouseY);
brush.stroke();
pastMouseX = mouseX;
pastMouseY = mouseY;
}
canvas.addEventListener('mousemove', event => {
console.log(event)
draw(event.offsetX, event.offsetY)} )
</script>
과거 mouse의 위치를 저장할 변수 2개를 만들고, 거기에 x,y값을 저장해줬습니다. 그러니 제가 원하는 대로 잘 나오는 것 같습니다.
이제 마우스가 움직일때마다 그림이 그려지면 안될것 같아 마우스가 눌려있을때 그려지고, 눌려있지 않으면 안그려지게 해야겠습니다.
<script>
let canvas = document.getElementById('canvas');
let brush = canvas.getContext("2d");
let pastMouseX = 0
let pastMouseY = 0
let isDraw = false
function draw(mouseX, mouseY){
if(isDraw) {
brush.beginPath();
brush.lineWidth = "1";
brush.strokeStyle = "green";
brush.moveTo(pastMouseX, pastMouseY);
brush.lineTo(mouseX, mouseY);
brush.stroke();
pastMouseX = mouseX;
pastMouseY = mouseY;
}
}
canvas.addEventListener('mousedown', () => isDraw = true )
canvas.addEventListener('mouseup', () => isDraw = false)
canvas.addEventListener('mousemove', event => {
console.log(event)
draw(event.offsetX, event.offsetY)} )
</script>
당당하게 쓰고 테스트를 했는데
어림도 없었습니다. 과거 마우스의 포인트 정보는 마우스가 눌렸을때가 아닌 마우스가 움직일때마다 설정을 해줘야 했는데 수정합니다.
<script>
let canvas = document.getElementById('canvas');
let brush = canvas.getContext("2d");
let pastMouseX = 0
let pastMouseY = 0
let isDraw = false
function draw(mouseX, mouseY){
if(isDraw) {
brush.beginPath();
brush.lineWidth = "1";
brush.strokeStyle = "green";
brush.moveTo(pastMouseX, pastMouseY);
brush.lineTo(mouseX, mouseY);
brush.stroke();
}
pastMouseX = mouseX;
pastMouseY = mouseY;
}
canvas.addEventListener('mousedown', () => isDraw = true )
canvas.addEventListener('mouseup', () => isDraw = false)
canvas.addEventListener('mousemove', event => {
console.log(event)
draw(event.offsetX, event.offsetY)} )
</script>
굳.

원하는 대로 마우스에따라 뭔가가 그려지긴 합니다. 하지만 선의 사이즈를 바꾸고 싶습니다.
만들어 줍니다.
<!document html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>
그림판 만들어보기
</title>
<link href="./assets/images/title-icon.png" rel="shortcut icon" type="image/x-icon">
<link type="text/css" rel="stylesheet" href="css/style.css">
</head>
<body>
<canvas id="canvas" width="500" height="500"></canvas>
<div>
<button type="button" onclick="lineWidthReSize('+')" >+1</button>
<button type="button" onclick="lineWidthReSize('-')">-1</button>
<div id="lindeWidth">10</div>
</div>
<script type="text/javascript" src="js/canvas.js"></script>
</body>
</html>
let canvas = document.getElementById('canvas');
let brush = canvas.getContext("2d");
let pastMouseX = 0
let pastMouseY = 0
let isDraw = false
let lineWidth = 10
function draw(mouseX, mouseY) {
if (isDraw) {
brush.beginPath();
brush.lineWidth = lineWidth;
brush.strokeStyle = "green";
brush.moveTo(pastMouseX, pastMouseY);
brush.lineTo(mouseX, mouseY);
brush.stroke();
}
pastMouseX = mouseX;
pastMouseY = mouseY;
}
canvas.addEventListener('mousedown', () => isDraw = true)
canvas.addEventListener('mouseup', () => isDraw = false)
canvas.addEventListener('mousemove', event => draw(event.offsetX, event.offsetY))
function lineWidthReSize(buttonType){
if(buttonType === '+') lineWidth++ ;
else{
if(lineWidth === 1){
alert('1이하로 줄일수 없습니다.')
}else{
lineWidth--
}
}
document.getElementById('lindeWidth').innerText = String(lineWidth)
console.log(lineWidth)
}
버튼으로 사이즈를 조정하는 것이 불편했습니다. 이걸 슬라이더로 만들어 줘야겠습니다.
<!document html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>
그림판 만들어보기
</title>
<link href="./assets/images/title-icon.png" rel="shortcut icon" type="image/x-icon">
<link type="text/css" rel="stylesheet" href="css/style.css">
</head>
<body>
<canvas id="canvas" width="500" height="500"></canvas>
<div>
<label for="slider">선 굵기</label><input type="range" min="1" max="100" value="10" id="slider" onchange="lineWidthReSizeForSlider()">
<button type="button" onclick="lineWidthReSize('+')" >+1</button>
<button type="button" onclick="lineWidthReSize('-')">-1</button>
<div id="lindeWidth">10</div>
</div>
<script type="text/javascript" src="js/canvas.js"></script>
</body>
</html>
let canvas = document.getElementById('canvas');
let brush = canvas.getContext("2d");
let pastMouseX = 0
let pastMouseY = 0
let isDraw = false
let lineWidth = 10
function draw(mouseX, mouseY) {
if (isDraw) {
brush.beginPath();
brush.lineWidth = lineWidth;
brush.strokeStyle = "green";
brush.moveTo(pastMouseX, pastMouseY);
brush.lineTo(mouseX, mouseY);
brush.stroke();
}
pastMouseX = mouseX;
pastMouseY = mouseY;
}
canvas.addEventListener('mousedown', () => isDraw = true)
canvas.addEventListener('mouseup', () => isDraw = false)
canvas.addEventListener('mousemove', event => draw(event.offsetX, event.offsetY))
function lineWidthReSize(buttonType){
if(buttonType === '+') lineWidth++ ;
else{
if(lineWidth === 1){
alert('1이하로 줄일수 없습니다.')
}else{
lineWidth--
}
}
document.getElementById('lindeWidth').innerText = String(lineWidth)
}
function lineWidthReSizeForSlider(){
let sliderValue = document.getElementById('slider')
lineWidth = sliderValue.value;
document.getElementById('lindeWidth').innerText = String(lineWidth)
}
이렇게해서 슬라이더로 간편하게 선의 굵기를 조절할수 있게 되었습니다.
너무 길어질것 같으니 다음 게시글에서 계속 작성해야겠습니다!
여기까지 저의 헤딩과정을 읽어주셔서 감사합니다!

'Toy Project' 카테고리의 다른 글
[드로잉윗유] 드로잉 윗유 제작기 기획부터! (0) | 2023.04.07 |
---|---|
node.js, socket.io를 사용해서 그림판 업그레이드 하기 (0) | 2022.12.22 |
[HTML, CSS, JS] 크롭앱 만들기 (0) | 2022.12.01 |
[HTML,CSS,JavaScript] 그림판만들기[3] (0) | 2022.11.24 |
[HTML, CSS, JavaScript]그림판 만들기[2] (0) | 2022.11.17 |