1. 도형합성및변환 1.1 도형합성 1.1.1 globalcompositeoperation 속성값 Ÿ globalcompositeoperation 속성을설명하면다양한기본합성동작을지정할수있다. 이속성을이용함으로써도형이그려진순서와상관없이겹쳐지는부분에대한처리가가능하다. 예제 <!DOCTYPE html><html><head> <script type="text/javascript"> function attr_values() { var canvas = document.getelementbyid('canvas'); context = canvas.getcontext('2d'); context.beginpath(); context.fillstyle = 'green'; context.fillrect(10, 10, 100, 100); context.globalcompositeoperation = 'lighter'; context.fillstyle = 'red'; context.arc(110, 110, 50, 0, 360*Math.PI/180, true); context.fill(); <body onload="attr_values();"> <canvas id="canvas" width="170" height="170" style="border:solid 1px #000000"> canvas 사용하기 </canvas> </body> </html> - 1 -
1.2 도형변환 Ÿ 캔버스의좌표계의이동, 회전및확대 / 축소기능을통한도형의변환을제공한다. Ÿ translate() 메서드는좌표공간의시작점을 (x,y) 로이동한다. Ÿ rotate() 메서드는좌표공간을시계방향으로회전한다. Ÿ scale() 메서드는좌표공간을수평 / 수직방향으로좌표공간을확대 / 축소한다. 예제도형변환 <!DOCTYPE html> <html><head> function polygon(context, x, y, radius, sides, startangle, anticlockwise) { if (sides < 3) return; //3각형이하는그리지않도록한다. var degree = (Math.PI * 2)/sides; degree = anticlockwise? -degree : degree; context.save(); // 드로잉상태를저정한다. context.translate(x,y); // 드로잉좌표공간을다각형중심좌표로이동한다. context.rotate(startangle); // 시작각도를중심으로그리도록하기위하여회전한다. context.moveto(radius,0); // 다각형의시작위치로이동한다. for (var i = 1; i < sides; i++) { // 면의수만큼루프를반복한다 context.lineto(radius*math.cos(degree*i),radius*math.sin(degree*i)); context.closepath(); // 패스를닫는다. context.restore(); // 기존드로잉상태를복구한다. function ScaleMirror() { // 그린도형을서로마주보게만든다. var canvas = document.getelementbyid("mycanvas"); var context = canvas.getcontext("2d"); context.linewidth = 10; context.linejoin = "round" context.fillstyle = "rgba(227,11,93,1.0)"; - 2 -
//polygon 메서드를사용하여삼각형을그린다. context.beginpath(); polygon(context,120, 120, 100, 3, (90 * Math.PI/2), false); context.stroke(); context.fill(); context.translate(canvas.width, 0); // 캔버스의중심으로중앙으로이동시킨다. context.scale(-1, 1);// 그리는방향을수평반대방향으로그리도록한다. //polygon 메서드를사용하여동일한조건으로삼각형을하나더그린다. polygon(context,120, 120, 100, 3, (90 * Math.PI/2), false); context.stroke(); context.fill(); <body onload="scalemirror();"> <canvas id="mycanvas" width="400" height="250" style="border: 10px inset #aaa"> 캔버스연습 </canvas> </body></html> 1.2.1 사용자정의변환 Ÿ 캔버스컨텍스트에서는변환행렬을직접조작할수있도록 transform() 메서드와 settransform() 메서드를제공한다. Ÿ transform() 메서드가지정된인수로행렬로현재변환행렬에적용시키기때문에연속해서이메서드를호출하면변환행렬값이누적된다. 반면에 settransform() 메서드는위에언급한바와같이현재변환행렬을원래값인단위행렬로재설정한다음 transform() 메서드를호출한다. 따라서이메서드를호출할때마다매번새로운변환행렬이적용된다. - 3 -
예제사용자정의변환 <!DOCTYPE html><html><head> function Transformation() { var canvas = document.getelementbyid('mycanvas'); var context = canvas.getcontext('2d'); var colors = new Array("red", "orange", "yellow", "green", "blue", "navy", "purple"); context.linewidth = 10; for (var i = 0; i <colors.length; i++) { // 호를반복해서그리도록한다. context.transform (1, 0, 0, 1, 0, 10); // 아래쪽으로 10픽셀만큼이동하는변환행렬 context.strokestyle = colors[i]; // 색상을적용시킨다. context.beginpath(); context.arc(200, 250, 250, 0, Math.PI, true); context.stroke(); <body onload="transformation();"> <canvas id="mycanvas" width="400" height="200" style="border: 10px inset #aaa"> 캔버스연습 </canvas> </body></html> 2. 텍스트그리기 2.1 텍스트테두리및채우기 Ÿ context.filltext( text, x, y [, maxwidth ] ) 는지정된위치에색이채워진텍스트를삽입한다. maxwidth가지정된경우, 텍스트는 maxwidth 폭크기에맞게조정된텍스트를채운다. Ÿ context.stroketext( text, x, y [, maxwidth ] ) 는지정된위치에테두리만있는텍스트를삽입한다. Ÿ context.measuretext( text ) 는현재글꼴에서주어진텍스트의폭을반환한다. 예제 텍스트테두리및채우기 <!DOCTYPE html><html><head> function filltext() { var canvas = document.getelementbyid('mycanvas'); var context = canvas.getcontext('2d'); - 4 -
gradient = context.createlineargradient(0, 0, 600, 0); gradient.addcolorstop("0", "magenta"); gradient.addcolorstop(".25", "blue"); gradient.addcolorstop(".50", "green"); gradient.addcolorstop(".75", "yellow"); gradient.addcolorstop("1.0", "red"); context.fillstyle = gradient; context.font = "50pt 궁서체 "; context.strokestyle = "red"; context.linewidth = 2; context.stroketext(" 컴퓨터과학 HTML5", 20, 65); context.filltext(" 컴퓨터과학 HTML5", 20, 140); context.fillstyle = 'blue'; context.stroketext(" 컴퓨터과학 HTML5", 20, 210); context.filltext(" 컴퓨터과학 HTML5", 20, 210); <body onload="filltext();"> <canvas id="mycanvas" width="600" height="400" > 캔버스연습 </canvas> </body> </html> 2.2 글꼴설정및텍스트배치 Ÿ context.font는현재글꼴의설정값을반환한다. font 속성값은글자스타일, 글자크기, 글꼴등으로지정할수있다. context.font = italic 15pt 굴림체 2.2.1 textalign 속성 Ÿ 현재텍스트의수평에대한맞춤 ( 정렬 ) 설정값을반환한다. 텍스트의맞춤을변경하기위하여설정될수있고, 기본값은 start이다. 지정할수있는값은 left, right, center, start, end이다. - 5 -
2.2.2 textbaseline 속성 Ÿ 현재텍스트의수직에대한기준선을지정한다. 수직위치의기준정렬을변경하기위하여설정될수있고, 기본값은 alphabetic이다. 지정할수있는값은 top, hanging, middle, alphabetic, ideographic, bottom이다. 예제 텍스트그리기 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <script type="text/javascript"> function arcto() { var canvas = document.getelementbyid("mycanvas"); var context = canvas.getcontext("2d"); context.font = "bold 40pt 궁서체 "; context.textalign = 'left'; context.textbaseline = 'top'; context.filltext(" 대한민국 ", 200, 100); context.font = "italic 50pt 굴림체 "; context.textalign = 'center'; context.textbaseline = 'bottom'; context.stroketext(" 대한민국 ", 200, 200); <body onload="arcto();"> <canvas id="mycanvas" width="500" height="400" >canvas 사용하기 </canvas> </body> </html> 3 이미지처리 3.1 이미지삽입관련메서드 Ÿ 이미지를그리기위해서는 drawimage() 메서드를사용하고, 이미지의일부나전체, 또는확대및축소하여캔버스어디든지그릴수있다. - 6 -
3.1.1 이미지삽입 Ÿ context.drawimage( 이미지, dx, dy) 는지정한이미지를원래크기로삽입한다. Ÿ context.drawimage( 이미지, dx, dy, dw, dh) 는이미지를지정한크기로삽입한다. Ÿ context.drawimage( 이미지, sx, sy, sw, sh, dx, dy, dw, dh) 는이미지의일부분을잘라내어삽입한다. 예제 <!DOCTYPE html><html><head> function drawimage() { var canvas = document.getelementbyid('mycanvas'); var context = canvas.getcontext('2d'); var img = new Image(); img.src = 'image.jpg'; img.onload = function(e) { context.drawimage(img, 10, 10, 380, 280); <body onload="drawimage();"> <canvas id="mycanvas" width="400" height="300" style="border: 10px inset #aaa"> 캔버스연습 </canvas> </body></html> - 7 -
3.1.2 이미지삽입예제 <!DOCTYPE html><html> <head> function drawimage() { var canvas = document.getelementbyid('mycanvas'); var context = canvas.getcontext('2d'); var img = new Image(); img.src = 'android.jpg'; img.onload = function(e) { context.drawimage(img, 10, 10); context.drawimage(img, 200, 10, 300, 300); context.drawimage(img, 10, 10, 100, 100, 550, 10, 100, 300); context.beginpath(); context.setlinedash([3,1]); context.linewidth =2; context.strokestyle="blue"; context.strokerect(200, 10, 300, 300); context.strokerect(550, 10, 100, 300); <body onload="drawimage();"> <canvas id="mycanvas" width="660" height="320" style="border: 2px inset #aaa"> 캔버스연습 </canvas> </body></html> 3.2 이미지조작 Ÿ 이미지데이터메서드를사용하면이미지의각픽셀에접근해서다양한조작을할수있다. createimagedata() 메서드를사용하여비어있는이미지에객체를생성할수있 - 8 -
Ÿ Ÿ Ÿ 다. getimagedata() 메서드를사용하여이미지픽셀에접근하고 putimagedata() 메서드를사용하여픽셀을다시이미지에넣을수있다. imagedata= context.createimagedata(sw, sh), imagedata = context.createimagedata( 이미지데이터 ) 는모든픽셀이투명한검은색으로초기화된 ImageData 객체를생성한다. imagedata = context.getimagedata(sx, sy, sw, sh) 는캔버스영역에지정된사각형영역에대한이미지를포함한 ImageData 객체를반환한다. context.putimagedata( 이미지데이터, dx, dy) 는캔버스에지정된 ImageData 객체의데이터를그린다. 3.2.1 이미지데이터처리 Ÿ 다음은 ImageData 객체를생성하는방법을나타낸것이다. imagecopy = context.createimagedata( canvas.width, canvas.height ) Ÿ 다음은캔버스영역에지정한영역에서 (0,0) 캔버스크기만큼 (canvas.width, canvas.height) 의이미지데이터를 imagedata 객체에반환하는방법을나타낸것으로, 캔버스에서이미지데이터를가져옴으로써, 이미지조작을자유자재로할수있다. imagedata = context.getimagedata( 0, 0, canvas.width, canvas.height ) Ÿ 생성된이미지배열데이터를복사하거나조작하기위해서는다음과같이반복문을통해서처리하게된다. for (var i=0; i < imagedata.data.length; i++) imagecopy.data[i] = imagedata.data[i]; Ÿ 가져온이미지데이터의배열을조작한다. for (var i=3; i < imagedata.data.length-4; i+=4) imagedata.data[i] = imagedata.data[i] / 2; Ÿ for (var i=0; i < imagedata.data.length-4; i+=4) { average = ( imagedata.data[i]+imagedata.data[i+1]+imagedata.data[i+2] ) / 3; imagedata.data[i] = imagedata.data[i+1] = imagedata.data[i+2] = average; 캔버스에서가져온이미지데이터를복사한후캔버스영역에출력하도록한방법을나타낸것이다. context.putimagedata ( imagecopy, 0, 0 ) 3.2.2 이미지데이터처리 Ÿ putimagedata() 메서드는이미지데이터의원하는부분만캔버스에출력할수있는기능을제공하고있다. 추가적인옵션 dirty* 를지정한다면이미지데이터의원하는 - 9 -
부분만을캔버스에출력할수있다. 예제이미지데이터처리 <!DOCTYPE html><html><head> <script type="text/javascript" src="canvas_lab.js"> function copyimage() { var canvas = document.getelementbyid('mycanvas'); var context = canvas.getcontext('2d'); // 그리는도형의그림자효과를설정한다. context.shadowblur = 5; context.shadowoffsetx = 5; context.shadowoffsety = 5; context.shadowcolor = 'rgba(0,0,0,0.75)'; // 다각형을그린다. context.beginpath(); context.strokestyle = "black" drawpolygon(context, 100, 100, 80, 8, Math.PI/2, false); // 팔각형외부를그린다 drawpolygon(context, 100, 100, 40, 8, Math.PI/2, true); // 팔각형내부를그린다 context.fillstyle="rgba(227,11,93,0.75)"; context.fill(); // 별을그린다. context.beginpath(); drawstar(context, 300, 100, 90, false); // 바깥쪽별을그린다. drawstar(context, 300, 100, 50, true); // 안쪽별을그린다. context.fillstyle="rgba(11,227,93,0.75)"; context.fill(); canvas.addeventlistener("click", function (){ // 캔버스의마우스클릭시 var canvas2 = document.getelementbyid("yourcanvas"); var context2 = canvas2.getcontext("2d"); - 10 -
// 캔버스에그려진이미지데이터를가져온다. var imagebuffer = context.getimagedata(0, 0, canvas.width, canvas.height); // 이미지데이터를원하는영역만다른캔버스에출력한다. context2.putimagedata(imagebuffer, 0, 0, 100, 0, 200, 200);, false); <body onload="copyimage();"> <canvas id="mycanvas" width="400" height="200" style="border: 10px inset #aaa"> 캔버스연습 </canvas> <canvas id="yourcanvas" width="400" height="200" style="border: 10px outset #aaa"> 캔버스연습 </canvas> <p> 왼쪽캔버스를마우스로클릭하면오른쪽캔버스에이미지를복사합니다.</p> </body> </html> 3.3 이미지데이터저장 Ÿ url = canvas.todataurl(type, quality) 은캔버스에그려진내용을 URL 문자열로반환해주는기능을제공한다. type은이미지의종류 ( image/jpeg, image/png ) 를나타내고 quality는이미지의품질을나타내는것으로 0.0 ~ 1.0( 손실이없는가장좋은품질 ) 사이의실수값을지정해야한다. 3.4 클리핑영역지정 Ÿ 캔버스영역에서드로잉을제한하도록해주는패스로정의된특수한영역을말한다. 컨텍스트가초기화될때, 클리핑영역의크기와캔버스의크기는동일하게된다. 클리핑영역은현재의클리핑영역과현재패스에서그려진영역이겹치는부분을계산하여새로운클리핑영역으로생성한다. Ÿ 클링핑영역은원하는클리핑모양의패스를지정한다음, clip() 메서드를호출하면된다. Ÿ 클리핑영역을설정한후 clearrect() 메서드를호출하면지워지는영역이클리핑영역으로제한된다. - 11 -
4. 애니메이션 4.1 기존방법의문제 Ÿ 애니메이션은 settimeout() 메서드나 setinterval() 메서드를사용한다. settimeout() 메서드는특정시간에처리할함수를한번만호출한다. setinterval() 메서드는특정시간마다처리할함수를반복적으로호출한다. Ÿ 이러한메서드들의문제는애니메이션을업데이트하기위한최적의주기가무엇인지모르기때문에개발자는가장간단한방법으로최소한의시간으로고정시킨다. 이러한방법들은과도한그리기로인한프레임손실, CPU주기가낭비되는등의문제가발생한다. Ÿ window 객체의 requestanimationframe() 및 cancelanimationframe() 메서드사용하도록한다. 4.2 스크립트기반애니메이션용타이밍컨트롤 Ÿ 캔버스에서는 requestanimationframe() 및 cancelanimationframe() 메서드를사용하여애니메이션을구현한다. 이메서드는브라우저가페이지디스플레이를업데이트해야할때만사용자애플리케이션에알리도록할수있으므로프레임손실문제를해결할수있다. Ÿ requestanimationframe() 메서드는다음애니메이션프레임을그릴준비가되면브라우저에게특정콜백을호출할수있도록요청한다. 다음애니메이션을그릴시간을알필요가없는장점이있다. requestid = window.requestanimationframe() Ÿ cancelanimationframe() 메서드는애니메이션프레임을업데이트하도록이전에예약되어있는콜백요청을취소하는데사용된다. window.cancelanimationframe( requestid ) 예제캔버스에서애니메이션구현 <!DOCTYPE html><html ><head> function drawimage() { var canvas = document.getelementbyid('mycanvas'); var context = canvas.getcontext('2d'); var requestid = 0; var x = 25, y = 25, rectwidth = 50, speed = 5; context.fillstyle="rgba(11,227,93,0.75)"; context.fillrect(x, y, rectwidth, rectwidth); function draw() { context.clearrect(0, 0, canvas.width, canvas.height); context.fillrect(x, y, rectwidth, rectwidth); - 12 -
function animate() { requestid = window.requestanimationframe(animate); x += speed; if(x <= 0 x >= (canvas.width - rectwidth)){ speed = -speed; draw(); canvas.addeventlistener("click", function (){ // 캔버스의이벤트리스너에서마우스클릭 if(requestid > 0) { // 애니메이션이동작중일때 window.cancelanimationframe(requestid); // 애니메이션을정지한다.. requestid = 0; // 핸들번호를초기화시킨다. else { // 애니메이션이정지상태이면다시시작한다. requestid = window.requestanimationframe(animate);, false); <body onload="drawimage();"> <canvas id="mycanvas" width="500" height="100" style="border: 10px inset #aaa"> 캔버스연습 </canvas> </body></html> - 13 -