1. 기본내용 1.1 캔버스 Ÿ canvas 요소는웹페이지에서자바스크립트를통해즉시그림을그리는데사용되며단순한그림표현을넘어여러효과와함께텍스트및애니메이션표현이가능하다. Ÿ 그림을그리기위해서는 <canvas> 를사용해서그림영역을지정하고, 자바스크립트를사용해서실제그림을그린다. 1.2 캔버스좌표시스템 Ÿ 캔버스의좌표시스템은 2D 컨텍스트로, 왼쪽상단모서리에있는평면직교표면을 (0,0) 으로시작해서오른쪽으로 X 좌표값이, 아래쪽으로 Y 좌표값이증가하는구조이다. 1.3 그림영역지정 Ÿ canvas 요소에가로및세로크기를지정하지않으면, 브라우저는자동으로가로 300 픽셀, 세로 150픽셀크기의캔버스를생성한다. width 속성과 height 속성을이용하여캔버스의크기를변경할수있다. 예제 <!DOCTYPE html><html><head></head> <body> <canvas id="canvas" width="700" height="400" style="border:solid 1px #ff0000"> 이브라우저는canvas를지원하지않습니다.</canvas> </body></html> - 1 -
Ÿ 캔버스의크기와드로잉표면의크기 <canvas> 요소의 width/height 속성사용하여변경하면캔버스크기를드로잉표면의크기로자동변경한다. CSS를사용해서캔버스크기를지정하는경우는드로잉표면의크기는변경할수없기때문에캔버스와드로잉표면의불일치로인하여예기치않은결과를발생시킬수있음에주의해야한다. Ÿ 브라우저화면의크기를기준으로캔버스크기를변경하는경우는윈도우객체의 innerwidth 및 innerheight 값을이용한다. 1.4 캔버스컨텍스트 Ÿ 컨텍스트는모든그래픽능력을제공한다. 캔버스는컨텍스트를위한컨테이너로서의역할만하고실제로캔버스에그리는등의기능들은모두컨텍스트를통하여처리한다. 1.5 캔버스상태의저장및복원 Ÿ 드로잉상태를저장하고복원하기위한 context.save() context.restore() 메소드를제공한다. Ÿ 드로잉상태는현재의변환행렬, 현재의클리핑영역으로구성되어있다. 예제 - 2 -
<!DOCTYPE html><html><head> function save_restore() { var canvas = document.getelementbyid("mycanvas"); var context = canvas.getcontext("2d"); / * 드로잉상태를 3 개저장 * / var colors = new Array ( "red", "blue", "green"); var alphas = new Array (0.2, 0.5, 0.8); for (var i = 0; i < 3; i++) { context.fillstyle = colors[i]; context.globalalpha = alphas[i]; context.save(); / * 저장된드로잉상태를복원하여원 3개를그린다 * / for (var i = 0; i < 3; i++) { context.restore(); context.arc((i+1) * 120, 120, 100, 0, Math.PI * 2, false); context.fill(); </head> <body onload="save_restore();"> <canvas id="mycanvas" width="500" height="250" style="border: 10px inset #aaa"> 캔버스에사각형그리기연습 </canvas></body> </html> 1.6 드로잉작업을위한기본형태 Ÿ 브라우저에그림을그리기위해서는캔버스요소를사용하여그림을그리고자하는영역을정의하고실제그림을그리는것은자바스크립트를사용하여그린다. - 3 -
Ÿ canvas 요소에폭과높이를지정하고, 자바스크립트에서사용할아이디값을지정한다. Ÿ canvas 요소의아이디를문서의 getelementbyid( 아이디 ) 메서드를호출하여 canvas 객체를생성하고 getcontext( 2d ) 메서드를호출하여그리기컨텍스트를생성한다. 예제 <!DOCTYPE html><html><head> <style> canvas { margin: 10px; padding 10px; border: 10px inset #aaa </style> function drawtext () { var canvas = document.getelementbyid("mycanvas"); var context = canvas.getcontext("2d"); context.font = "24pt 굴림체 "; context.fillstyle = "maroon"; context.filltext(" 그림을그립시다 ", canvas.width/2-130, canvas.height/2 + 15); </head> <body onload="drawtext();"> <canvas id="mycanvas" width="300" height="200"> 이브라우저는 canvas 요소를지원하지않습니다. </canvas> </body></html> - 4 -
2. 사각형그리기 2.1 사각형그리기 Ÿ 시작점 (x, y) 을제공하고, 다른 2 개는사각형의폭 (W) 및높이 (H) 를제공한다. 2.2 사각형그리기관련메서드 Ÿ context.fillrect (x, y, w, h) 메서드는색이채워진사각형영역을그린다. 현재의채우기스타일 fillstyle 속성을사용하여지정한사각형영역의캔버스에채워진사각형을그린다. Ÿ context.strokerect (x, y, w, h) 메서드는테두리만있는사각형영역을그린다. Ÿ context.clearrect (x, y, w, h) 메서드는지정한사각형영역을지운다. 현재클리핑영역과교차하는지정한사각형영역에있는모든픽셀을투명한검은색으로채운다. 예제사각형그리기 <!DOCTYPE html><html><head> function rect() { var canvas = document.getelementbyid("mycanvas"); var context = canvas.getcontext("2d"); context.linejoin = "round"; context.linewidth = 20; context.strokestyle = "blue"; context.fillstyle = "green"; context.strokerect(50, 100, 200, 200); context.fillrect(300, 100, 200, 200); context.fillrect(550, 100, 200, 200); context.clearrect(600, 150, 100, 100); </head> <body onload="rect();"> <canvas id="mycanvas" width="800" height="400" style="border: 10px inset #aaa"> - 5 -
캔버스에사각형그리기연습 </canvas> </body> </html> 3. 선그리기 3.1 패스와서브패스 Ÿ 캔버스에서는각도형들을이루는선들의집합을패스 (Path) 라고하고각각의선을서브패스라고한다. Ÿ 컨텍스트의메서드를이용하여선이나도형을그리고자할때는 beginpath() 함수를호출하여패스를초기화한다. 그리고다양한메서드를사용하여패스를지정하고선이나도형을그린다. 마지막으로지정한패스를닫고선이나도형을출력해야한다. Ÿ beginpath() 메서드는현재패스를초기화한다. 이전까지그렸던패스를모두초기화하고새로운패스를그린다는의미이다. Ÿ closepath() 메서드는현재패스를닫는다. 패스그리는것을종료한다는의미이다. Ÿ lineto(x, y) 메서드는직선을연결한다. 이전위치에서의점과현재서브패스에주어진점을추가하여선을그린다. Ÿ moveto(x, y) 메서드는주어진점으로시작하는새로운서브패스를만든다. Ÿ stroke() 메서드는현재패스또는주어진패스의서브패스를현재의선스타일로그린다. Ÿ fill() 메서드는현재패스또는주어진패스의서브패스를현재의채우기스타일로채운다. Ÿ rect(x, y, w, h) 메서드는사각형을그린다. 3.2 선그리기 Ÿ 시작점을지정하기위해서는 moveto() 메서드를사용한다. 그리고다음위치까지의점을지정하여선을그리기위해서는 lineto() 메서드를사용한다. 그리고 stroke() 메서드를사용해서선을출력한다. - 6 -
예제선그리기 <!DOCTYPE html><html><head> function Line() { var canvas = document.getelementbyid("mycanvas"); var context = canvas.getcontext("2d"); context.moveto(20, 20); context.lineto(150, 150); context.lineto(150, 20); context.lineto(280, 150); </head> <body onload="line();"> <canvas id="mycanvas" width="800" height="400" style="border: 10px inset #aaa"> 캔버스에사각형그리기연습 </canvas> </body></html> 3.3 선의경계와픽셀경계 Ÿ 일반적으로픽셀을다루는컴퓨터그래픽시스템에서는픽셀의위치를정수단위로처리하기때문에픽셀의경계또한정수단위로이루어진다. 그리고캔버스컨텍스트에서는선을그릴때두께를지정할수있기때문에선의중간에서상하 / 좌우 0.5 픽셀만큼씩그리려고한다. 따라서왼쪽그림과같이 1.5에서상하 0.5 픽셀만큼확장하고, 2.5에서상하 0.5픽셀만큼확장하기때문에결국에는 2픽셀크기만큼선이그려진다. 그러나오른쪽그림에서는상하 0.5 픽셀만큼씩확장하면정수단위의픽셀만큼씩확장하면정수단위의픽셀경계가되기때문에 1픽셀만큼만그려지는것을볼수있다. 정확한픽셀두께만큼의선을그리려면펙셀사이의실수값위치를지정해야함을잊지말자. - 7 -
3.4 다각형그리기 Ÿ 선그리기메서드에서 closepath() 메서드를사용하면다각형을그릴수있다. Ÿ closepath() 메서드는선이마지막으로종료된지점과최초의지점을자동을연결한다. 예제선그리기 <!DOCTYPE html><html><head> function polygon() { var canvas = document.getelementbyid("mycanvas"); var context = canvas.getcontext("2d"); context.moveto(150, 10); context.lineto(80, 350); context.lineto(350, 350); context.lineto(280, 10); context.closepath(); </head> <body onload="polygon();"> <canvas id="mycanvas" width="600" height="400" style="border: 10px inset #aaa"> 캔버스에그리기연습 </canvas> </body> </html> 3.4.1 정다각형을그리는알고리즘 Ÿ 정다각형은모든각도와모든측면이동일하다. 또한모든꼭지점은원안에위치한다는것을확인할수있다. Ÿ 입력 : 좌표 (x, y), 반지름 (R), 면의수 (N), 시작각도 (startangle) - 8 -
Ÿ 원의반지름 (R) 과면의수 (N) 를계산한다. (3 각형은 3 면, 4 각형은 4 면, 5 각형은 5 면 ) if ( N < 3) return; Ÿ 원의중심으로부터정다각형의각측면에의한각도 (360/N) 계산한다. Ÿ var degree = (Math.PI*2)/N; context.save(); context.translate(x,y); context.rotate(startangle); 첫번째꼭지점의위치를 (R, 0) 으로지정 context.moveto(r, 0); Ÿ 면의수 (N) 만큼루프를통해서꼭지점이위치하는각도계산한다. 각꼭지점들끼리의드로잉을수행한다. for (var i=0; i<n; i++) context.lineto(r*math.cos(degree*i), R*Math.sin(degree*i)); context.closepath(); context.restore(); 3.5 점선그리기 Ÿ context.setlinedash(segments) 는현재점선의패턴을설정한다. segments 값은점선의패턴으로선이그려지는부분과그려지지않는부분이반복되는배열이된다. Ÿ segment = context.getlinedash( ) 는현재점선의패턴을반환한다. Ÿ context.linedashoffset [=value] 점선모양의패턴과동일한단위에서의위상오프셋을반환한다. 선의모양의점선패턴으로변경한다. Ÿ setlinedash() 에서 segments 인자의사용방법은다음그림과같다. - 9 -
예제점선그리기 <!DOCTYPE html><html><head> function LineDash() { var canvas = document.getelementbyid("mycanvas"); var context = canvas.getcontext("2d"); // 사각형그리기 context.setlinedash([5,2]); context.rect(30,15,100,100); // 삼각형그리기 context.setlinedash([1,2]); context.moveto(145,115); context.lineto(195,15); context.lineto(245,115); context.closepath(); // 다각형그리기 context.fillstyle = 'lightblue'; context.setlinedash([15]); context.moveto(260,115); context.lineto(275,95); context.lineto(305,15); context.lineto(345,65); context.lineto(345,115); context.closepath(); - 10 -
context.fill(); </head> <body onload="linedash();"> <canvas id="mycanvas" width="400" height="150" style="border: 10px inset #aaa"> 캔버스에점선그리기연습 </canvas> </body> </html> 3.6 선스타일지정 Ÿ 선의색상을지정하고자할때는 strokestyle 속성을사용한다. context.strokestyle [=value] Ÿ 선의두께를지정할때는 linewidth 속성을사용한다. context.linewidth [=value] Ÿ 선의연결부분의스타일지정할때는 linejoin 속성을사용한다. context.linejoin [= bevel round miter( 기본 ) ] Ÿ 선의끝부분의스타일을지정할때는 linecap 속성을사용한다. context.linecap [= butt( 기본 ) round square ] 예제선스타일지정 <!DOCTYPE html><html><head> function LineJoin() { var canvas = document.getelementbyid("mycanvas"); var context = canvas.getcontext("2d"); var linestart = 50, lineend = 200, ystart = 50; context.linewidth = "25"; // bevel corner. - 11 -
context.strokestyle = "Red"; context.linejoin = "bevel"; // 선의연결부분스타일을지정. context.moveto(linestart, ystart); context.lineto(lineend, ystart); context.lineto(lineend, ystart + 150); // round corner. context.strokestyle = "blue"; context.linejoin = "round"; // 선의연결부분스타일지정 context.moveto(linestart + 200, ystart); context.lineto(lineend + 200, ystart); context.lineto(lineend + 200, ystart + 150); // miter. context.strokestyle = "green"; context.linejoin = "miter"; // 선의연결부분스타일을지정 context.moveto(linestart + 400, ystart); context.lineto(lineend + 400, ystart); context.lineto(lineend + 400, ystart + 150); </head> <body onload="linejoin();"> <canvas id="mycanvas" width="650" height="250" style="border: 10px inset #aaa"> 캔버스연습하기 </canvas> </body> </html> Ÿ 선의연결부분의스타일이 miter인경우 miter 길이의비율을지정하고자할때는 miterlimit 속성을사용한다. 선의 miter 연결부분의한계비율 = (miter 길이 ) / ( 선두께의 1/2 크기 ) context.miterlimit [= value] - 12 -
예제 miterlimit 속성 <!DOCTYPE html><html><head></head> <body><canvas id="mycanvas" width="200" height="200" style="border: 10px inset #aaa"> 캔버스연습하기 </canvas> var canvas = document.getelementbyid('mycanvas'); var context = canvas.getcontext('2d'); // 첫번째연결선을그린다. context.linewidth = 20; context.miterlimit = 3.0; context.strokestyle = "lightblue"; context.moveto(30, 140); context.lineto(50, 80); context.lineto(70, 140); // 보조선을선중간에그린다 context.linewidth = 1; context.strokestyle = "red"; context.moveto(30, 140); context.lineto(50, 80); context.lineto(70, 140); // 두번째연결선을그린다. context.linewidth = 20; context.miterlimit = 10.0; context.strokestyle = "lightblue"; context.moveto(130, 140); context.lineto(150, 80); context.lineto(170, 140); // 보조선을선중간에그린다 context.linewidth = 1; context.strokestyle = "red"; context.moveto(130, 140); context.lineto(150, 80); context.lineto(170, 140); - 13 -
</body> </html> - 14 -