YongWook's Notes

<WebGL> 그림판 만들기 본문

-software/python

<WebGL> 그림판 만들기

글로벌한량 2016. 9. 30. 13:59

HTML5와 Javascript를 이용하여 WebGL기반 그림판을 만들어 보았다.
코드는 다음의 링크에서 볼 수 있다.


https://github.com/YongWookHa/drawingBoard/blob/master/drawingBoard.html


script부분을 별도 파일로 분리하지 않아 조금 지저분한 면이 있지만 간략적인 설명을 하자면 다음과 같다.

그래픽 구현은 HTML5에서 지원하는 canvas 태그 위에서 이루어진다. 여기서, Graphic은 context.beginPath()로 시작하여 좌표를 이용하여 그리고 싶은 내용을 논리적으로 묘사 해놓고 context.stroke()를 통해 canvas상에 나타내는 구조로 구현된다. 원하는 그림을 그린 후에는 context.closePath()로 작업의 끝을 알린다. canvas 위에 마우스를 클릭했을 때 이를 감지하기 위해 onmousedown과 onmouseup을 사용하여 적절한 함수를 호출한다. 또한 canvas에 그려지는 object의 width나 color 속성은 context에 탑재된 몇 가지 함수로서 가능하다. 구현된 각각의 기능에 대한 상세한 설명은 다음과 같다.
context class에서 제공하는 함수 및 attribute 정보 : http://www.w3schools.com/tags/ref_canvas.asp

1.선분
가장 기본적인 기능인 선분 그리기는 context.moveTo(x,y) 와 context.lineTo(x,y)로 구성되어있다. 전자는 선분의 시작점, 후자는 끝점을 나타낸다.

2.원
원은 context.arc(centerX,centerY,radius,startAngle,endAngle,counterclockwise), 5개의 인자를 받는 함수로 그릴 수 있다. 처음 마우스를 누르는 지점으로부터 마우스를 떼는 지점까지의 거리를 지름으로 한 원을 그리기 위해 figX, figY라는 마우스를 누르는 순간의 좌표를 임시적으로 저장하는 전역변수를 선언하여 활용하였다. (figX, figY)와 마우스를 떼는 순간의 좌표인 (x,y)사이의 Euclidean distance의 1/2를 반지름, radius으로 사용했다. 

3.사각형
사각형은 context.rect(startX,startY,endX,endY)로 그려낼 수 있다. 마우스를 누를 때와 뗄 때의 두 점을 기준으로 그리기 때문에 원과 마찬가지로 figX와 figY의 전역변수를 이용하였다. 

4.다각형
다각형을 그리기 위해서는 두 가지 단계가 필요하다. 처음에는 하나의 선분을 그리고 해당 선분의 끝점과 다음의 입력점들을 이어주는 것이 첫 번째 단계다. 이를 위해서는 poly_first라는 flag를 이용하여 첫 번째 입력인지 확인하고 만약 그렇다면 선분을 그리는 것과 같은 일을 하게 해야 한다. 만약 첫 번째 입력이 아니라면, 이전에 그려진 선분의 마지막점부터 현재 입력점까지 선분을 그려주는 일을 한다. 두 번째 단계는 마우스 오른쪽 버튼의 입력을 받았을 때 다각형 그리기의 작업이 끝난 것으로 간주하고 마지막 입력점과 최초 선분의 시작점을 이어주는 일이다. 이 과정에서 마우스 오른쪽 버튼의 입력을 확인하기 위해 event.which==3임을 확인시킨다. which==1일때는 마우스 왼쪽버튼이고 2일때는 가운데 휠버튼이다.

5.곡선
베지어 곡선을 그리기 위해서는 네 개의 점이 필요하다. context.moveTo(x,y)으로 P0을 입력해주고 cp1_x, cp1_y, cp2_x, cp2_y 전역변수를 설치해주어 P1, P2를 입력받는다. 마지막으로 입력되는 P3점에서 context.bezierCurveTo()함수의 인자로 P1, P2, P3를 모두 넣어주면 된다.

6.색 채우기
색 채우기는 사각형에 적용되는 속성으로, context.fillStyle에 Color 속성값을 넣어서 설정하고 context.fill()으로 색깔을 채워준다. 색상 선택의 편의를 위해 각각의 색상들을 버튼으로 구현하였다. input(button)태그의 style속성에 "border:none;"을 추가하여 버튼같지 않은 느낌을 연출하였다. 또한 현재 선택된 색상을 디스플레이하기 위해 가장 첫 번째 줄에 단독으로 위치한 하나의 버튼은 다른 색상 변경 버튼들이 클릭될 때 마다 호출되는 함수에 document.getElementById().style.backgroundColor를 변경하는 코드를 삽입하였다.

7.패턴
외부 파일로부터 패턴이미지를 받기 위해서는 input 태그의 type을 file로 지정하여 새로운 파일을 불러오는 작업을 해야한다. 하지만 file type의 input 태그는 보안상의 이유인지 스타일링하기가 매우 까다롭다. 따라서 style 속성에 "display:none;"을 추가하여 숨겨버리고 다른 button 태그를 만들어서 스타일링을 하고 이 태그의 onclick 함수를 file type의 input 태그로 연결하는 일종의 편법이 자주 이용되고 있다고 한다. 과제에서는 스타일링을 위해 만든 button 태그의 onclick 함수인 pattern_clicked에서 file type의 input 태그를 클릭하는 이벤트를 발생시키도록 하는 코드를 삽입하여 onchange 함수인 loadImage를 실행시킨다.

8.선 색상 변경
선 색상은 context.strokeStyle에 Color를 할당해주는 것으로 변경할 수 있다. 색 채우기에 이미 한번 구현했던 대로 각각의 색상 선택 버튼을 구현하였고 현재 색상을 디스플레이하는 버튼을 배치하였다. 

9.선 굵기
context.lineWidth에 숫자를 할당하여 바꿀 수 있는 선의 굵기는 style속성에 "border:none"을 입력하여 테두리가 없어진 버튼에 height를 조정하여 선의 굵기를 가시적으로 보여주는 버튼을 만들어 직관적인 선택이 가능하도록 하였다. 

10. 저장
canvas에 그려진 이미지를 저장하기 위해서 디스플레이 되지 않는 element를 만들고 element.download에 default file name을 입력할 수 있다. 이 default file name을 canvas.png로 설정하여 canvas에 그려진 모든 객체를 표현할 수 있는 양식으로 png format을 제안하였다. 이후에는 element.herf에 canvas.toDataURL()으로 url을 입력해줘서 다운로드가 가능하게 한다. 

11. 불러오기
불러오기의 경우도 앞서 구현한 패턴과 마찬가지로 스타일링의 편의를 위해 file type의 input 태그를 숨기고 input태그로 연결시켜주는 새로운 button을 만들어주는 방식을 취했다. 선택된 이미지파일을 context.drawImage(image,startX,startY) 함수를 통해 canvas에 그려낸다.

Comments