HTML5 웹프로그래밍입문 11 장. 캔버스
목차 11.1 캔버스이해하기 11.2 캔버스기본 API 사용하기 11.3 캔버스고급기능사용하기 2
11.1 캔버스이해하기 11.1.1 캔버스의특징 11.1.2 캔버스시작하기 3
HTML5 캔버스 자바스크립트를이용해서웹문서상에그림그리는기능 HTML5 이전 직접이미지파일을 <img> 태그를이용해서문서상에포함 자바애플릿이용 플래시이용 HTML5 캔버스 자바스크립트만을이용해서그림을그릴수있다 별도의플러그인이나프로그램설치없이가능 이미지나그림을합성, 변환조작도가능 4
캔버스의특징 캔버스좌표계 : 사각평면의 2 차원좌표계 이차원 (2D) 이미지표현 => x, y 2개의축 왼쪽상단모서리가원점 (0, 0) (0, 0) x 축 픽셀 (pixel) 좌표계상의각각의정사각형네모칸 이미지를구성하는점이며색상을가진다. y 축 (30, 20) 비트맥그래픽 (Bitmap graphics) 픽셀만으로이미지를표현하고저장하는형태 캔버스의도형이나그림, 글씨등을 2차원비트맵으로저장 이미그려진도형이나그림을확대하는등은작업은불가능 5
캔버스시작하기 캔버스요소 : <canvas> 태그이용, width, height 속성으로캔버스크기지정, DOM 접근을위해 id 지정 컨텍스트 (context) 객체 캔버스에내용을채우기위한객체 <canvas> 요소객체에접근한후 getcontext("2d") 메소드실행 <body> <canvas id="mycanvas" width="300" height="200"></canvas> <script type="text/javascript"> var canvas = document.getelementbyid("mycanvas"); 캔버스요소의정의 var context = canvas.getcontext("2d"); context.moveto(50, 50); 캔버스컨택스트가져오기 context.lineto(200, 50); </script> 그림을그리는자바스크립트코드 </body> 6
11.2 캔버스기본 API 사용하기 11.2.1 기본도형그리기 11.2.2 기본도형꾸미기 11.2.3 이미지와글자그리기 7
캔버스기본도형그리기 캔버스기본 API 컨텍스트객체의메소드를호출함로써그림이그려짐 캔버스컨텍스트의선그리기메소드 선긋기, 경로, 곡선등 현재위치에서다음지점까지선을연결하는방식 현재위치이동 : moveto(x,y) 메소드 선을그린경우에는마지막지점으로현재위치이동 캔버스컨텍스트메소드 context.moveto(x, y) context.lineto(x, y) context.rect(x, y, width, height); 기능및설명선의시작지점을 (x, y) 로이동현재위치에서 (x, y) 까지선그리기왼쪽위모서리가 (x, y) 지점이고, 가로와세로변의크기가 width, height인사각형그리기현재지정된색상과모양으로선을그린다. stroke() 메소드를실행하지않으면선이안그려진다. 8
직선, 사각형그리기예제 var canvas = document.getelementbyid("mycanvas"); var context = canvas.getcontext("2d"); context.moveto(50, 50); context.lineto(200, 50); context.lineto(200, 100); context.lineto(100, 100); context.lineto(50, 150); context.lineto(150, 180); (50, 50) (200, 50) (100, 100) (200, 100) (50, 150) (150, 180) var canvas = document.getelementbyid("mycanvas"); var context = canvas.getcontext("2d"); context.rect(50, 50, 100, 100); context.rect(20, 20, 180, 180); context.rect(120, 120, 50, 50); (20, 20) (50, 50) (120, 120) (150, 150) (170, 170) 9 (200, 200)
원호그리기예제 context.arc(x, y, r, startangle, endangle, anticlockwise) (x, y) 를원점으로하고반지름 r인원호. 시작각도와끝각도를지정 anticlockwise 값을 false로설정하면시계방향 ( 기본값 ) context.beginpath(); context.arc(30, 100, 20, 0, 1.5*Math.PI); // Math.PI 상수를이용해각도지정 beginpath(); 가없으면선이연속된다. context.beginpath(); context.arc(110, 100, 40, 1*Math.PI, 1.5*Math.PI, true);// 반시계방향원호 context.closepath(); // 경로시작점까지직선으로연결하며경로를종료한다. context.beginpath(); context.arc(240, 100, 60, 0, 2*Math.PI); // 360 도원호를그려원그리기 10
곡선그리기예제 context.quadraticcurveto(cx, cy, x, y); 하나의제어점 시작점은현재위치, (cx, cy) 가제어점, 끝점은 (x, y) context.beziercurveto(cx1, cy1, cx2, cy2, x, y); 시작점은현재, 두개제어점은 (cx1, cy1) 과 (cx2, xy2), 끝점 (x, y) context.moveto(50, 200); context.quadraticcurveto(100, 10, 200, 200); context.moveto(300, 200); (100, 10) context.beziercurveto(300, 100, 600, 100, 450, 200); 제어점 제어점1 (300, 100) 제어점2 (550, 100) (50, 100) (200, 100) 시작점끝점 Quadratic 곡선 (300, 200) 시작점 Bezier 곡선 (450, 200) 끝점 11
경로그리기 연속된선그리기를통한경로그리기 context.beginpath() 경로의시작설정 context.closepath() 경로지정을종료 처음경로시작지점으로선을연결하여경로를완성 12
선꾸미기예제 linewidth 선의두께 ( 픽셀개수 ) strokestyle 선의색상 예 ) "blue" 혹은 "#0000ff" 등 linecap 선의양쪽끝모양 "butt", "round", "square" context.beginpath(); context.moveto(10, 20); context.lineto(100,20); context.linewidth = 20; context.strokestyle = "blue"; context.linecap = "butt"; context.beginpath(); context.moveto(10, 60); context.lineto(100, 60); context.strokestyle = "red"; context.linecap = "round"; context.beginpath(); context.moveto(10, 100); context.lineto(100, 100); context.strokestyle = "green"; context.linecap = "square"; 13
도형꾸미기예제 linejoin 선이꺽이는모서리모양 "miter", "round", "bevel" fillstyle 도형의내부를색칠할색상값 context.fill(); 현재 fillstyle 색상으로도형채우기 이전 fill() 메소드이후의모든도형 context.beginpath(); context.rect(20, 20, 50, 80); context.linewidth = 20; context.strokestyle = "black"; context.linejoin = "miter"; context.fillstyle = "grey"; context.fill(); context.beginpath(); context.rect(110, 20, 50, 80); context.strokestyle = "black"; context.linejoin = "round"; context.fillstyle = "pink"; context.fill(); context.beginpath(); context.rect(200, 20, 50, 80); context.strokestyle = "black"; context.linejoin = "bevel"; context.fillstyle = "yellow"; context.fill(); 14
이미지그리기 기존에이미지를포함하려면 <img> 태그이용 캔버스에이미지그리기 Image 객체생성 : Image() 생성자이용 drawimage() 메소드 캔버스컨텍스트에서이미지그리기 는메소드 사이즈조정, 크롭 (crop) 등의기능도가능 15
이미지그리기예제 기존에이미지를포함하려면 <img> 태그이용 캔버스에이미지그리기 Image 객체생성 : Image() 생성자이용 drawimage() 메소드 캔버스컨텍스트에서이미지그리기 var canvas = document.getelementbyid("mycanvas"); var context2d = canvas.getcontext("2d"); var imgobj = new Image(); imgobj.src = "clownfish.jpg"; imgobj.onload = function() { // (50, 50) 지점에원래크기그대로이미지그리기 context2d.drawimage(imgobj, 50, 50); // 크기조정하기 : (600, 50) 지점에 250 x 100 크기로이미지그리기 context2d.drawimage(imgobj, 600, 50, 250, 100); 이미지사이즈조정 // 크기조정하기 : (900, 50) 지점에 200 x 200 크기로이미지그리기 context2d.drawimage(imgobj, 900, 50, 200, 200); 16
이미지그리기예제 Image crop 원본이미지에서자르고, 캔버스에그린다... // 이미지자르기후크기조정 : // 1) 원본이미지 (150, 100) 지점에서 150 x 150 크기의이미지를자른다. // 2) Canvas 의 (600, 300) 지점에 100 x 100 크기로그리기 context2d.drawimage(imgobj, 150, 100, 150, 150, 600, 300, 100, 100); } // 이미지자르기후크기조정 : // 1) 원본이미지 (250, 100) 지점에서 250 x 150 크기의이미지를자른다. // 2) Canvas 의 (750, 300) 지점에 125 x 75 크기로그리기 context2d.drawimage(imgobj, 250, 100, 250, 150, 750, 300, 125, 75); 17 이미지크롭 이미지사이즈조정
캔버스에글자그리기 비트맵방식으로캔버스에텍스트그리기 텍스트를그려넣기전에폰트, 크기, 정렬방법등을결정 삽입된글자를수정하거나크기를조정하는것은불가능 글자그리기메소드 context.font : 글자체지정. 이탤릭체, 크기, 폰트등한번에지정 context.textalign : 텍스트정렬. "left", "right", "center", "start", "end" context.fillstyle : 글자의색상, 예 ) "blue" 혹은 "#0000ff" 등 context.filltext() : 지정된위치에글자를그린다 글자외곽선그리기 context.strokestyle : 글자의외곽선색상 context.linewidth : 외곽선의선두께 context.stroketext(text, x, y) : (x, y) 위치에 text 외곽선을그린다 18
글자그려넣기예제 context.rect(0, 0, 400, 300); var text1 = "HTML5 Text Drawing!"; var text2 = "Left aligned text"; var text3 = "Center aligned text"; var text4 = "Right aligned text"; context.font = "italic 16pt Times New Roman"; context.fillstyle = "blue"; context.filltext(text1, 200, 50); context.font = "12pt Tahoma"; context.fillstyle = "red"; context.textalign = "left"; context.filltext(text2, 200, 100); context.font = "bold 24pt Courier New"; context.strokestyle = "black"; context.textalign = "center"; context.linewidth = 1; context.stroketext(text3, 200, 150); context.linewidth = 2; context.stroketext("linewidth=2", 200, 200); context.font = "bold 16pt Batang"; context.fillstyle = "green"; context.textalign = "right"; context.filltext(text4, 200, 250); 19
11.3 캔버스고급기능사용하기 11.3.1 그리기효과 11.3.2 변환효과 11.3.3 기타고급기능 20
그리기효과 합성 (composition) 효과 그림자효과 : shadow shadowcolor, shadowblur, shadowoffsetx, shadowoffsety 투명도조절 : globalalpha 0과 1 사이의실수값, 0이완전투명 지정한도형모양으로잘라내기 : clip clip() 메소드가바로이전에정의된경로로도형자르기 21
그리기효과예제 context.beginpath(); context.rect(40, 10, 60, 100); context.closepath(); context.clip(); 클립효과사용시유의사항 잘라내고자하는그림을그리기이전에 clip() 메소드를실행 clip() 메소드실행이전에그려진그림은자르기효과가적용안됨 context.beginpath(); context.rect(20, 20, 60, 60); context.fillstyle = "green"; context.shadowcolor = "blue"; context.shadowblur = 30; context.shadowoffsetx = 10; context.shadowoffsety = 20; context.fill(); context.beginpath(); context.arc(80, 30, 30, 0, 2*Math.PI); context.fillstyle = "red"; context.globalalpha = 0.5; context.shadowcolor = "transparent"; context.fill(); (a) clip() 메소드를실행하지않은경우 (b) clip() 메소드를실행한경우 22
변환효과 기본변환 (transformation) 그림을그려넣을때위치이동, 크기변환, 회전등의기능을수행 translate(x, y); 이동변환, (x, y) 만큼이동 scale(x, y); 크기변환, 가로세로방향의배율 (x, y) rotate( 회전각도 ); 회전변환, 회전각도는 radian 값, 회전중심점은왼쪽위모서리 23
기본변환예제 var canvas = document.getelementbyid("mycanvas"); var context2d = canvas.getcontext("2d"); var imgobj = new Image(); imgobj.src = "clownfish.jpg"; imgobj.onload = function() { // original drawing context2d.drawimage(imgobj, 50, 50); // 이동변환 context2d.translate(800, 50); // 이동 context2d.drawimage(imgobj, 50, 50); // 크기변환 context2d.scale(1.2, 0.33); // 가로 1.2, 세로 1/3 배스케일 context2d.drawimage(imgobj, 0, 1500); } // 회전변환 context2d.rotate(45); context2d.drawimage(imgobj, 1000, 1000); 24
상하 / 좌우대칭변환 scale() 메소드의인자값을조정하여구현 // 좌우대칭 context.scale( 1,1); // 상하대칭 context.scale(1, 1); 현재까지지정된변환이나사용자정의변환행렬을초기화 settransform() 메소드이용 아무런변환을지정하지않은기본상태로초기화 context.settransform(1, 0, 0, 1, 0, 0); 25
데이터 URL 로저장하기 그림을 PNG(Portable Network Graphics) 등형식으로저장 캔버스의 todataurl() 메소드이용 그림을 todataurl() 메소드를이용해서 PNG 형태의데이터로변환 이를캔버스요소의 src 속성으로지정하면파일로저장이가능 유의사항 var dataurl = canvas.todataurl(); canvasdom.src = dataurl; todataurl() 은캔버스컨텍스트가아닌캔버스요소객체의메소드 캔버스비트맵초기화 가장간편한방법은 clearrect(x, y, width, height) 메소드이용 (x, y) 위치를기준으로 width, height 의크기의비트맵을초기화 26
데이터 URL 저장예제 <canvas id="mycanvas" width="400" height="200"></canvas>... <img id="canvasimage" /> <script>... context.rect(0, 0, 400, 200); context.fillstyle = "grey"; context.fill(); var text1 = "HTML5 Text Drawing!"; context.font = "24pt Tahoma"; context.fillstyle = "red"; context.filltext(text1, 50, 50); 캔버스이미지 ( 왼쪽 ) 과데이터 URL 방식으로저장한 PNG 이미지 ( 오른쪽 ) context.linewidth = 1; context.font = "32pt San Serif"; context.strokestyle = "blue"; context.stroketext("linewidth=1", 100, 150); // Canvas 이미지를 data URL 로저장한다. 기본형식은 PNG 포맷이다. var dataurl = canvas.todataurl(); // dataurl 을 "canvasimage" 엘리먼트의 src 속성으로지정한다. document.getelementbyid("canvasimage").src = dataurl; 27
마우스로그림그리기예제 캔버스상에마우스이벤트를활용해그림그리기 마우스버튼을누른후이동위치를따라연속으로직선을그림 mousemove 이벤트가발생할때마다 lineto() 메소드호출 <body onmousedown="start();" onmousemove="draw();" onmouseup="stop();"> <canvas id="mycanvas" width="600" height="600" style="border style: solid;"></canvas> <script type="text/javascript"> ( 중간생략 ) var stopped = true; function start() { e = window.event; context.moveto(e.clientx 10, e.clienty 10); stopped = false; } function stop() { stopped = true; } function draw() { if (!stopped) { e = window.event; context.lineto(e.clientx 10, e.clienty 10); } } </script> </body> 28