그리드
본격적으로 시작하기 전에 캔버스의 그리드나 좌표 공간에 대해 논의해야 합니다. 이전 페이지의 HTML 템플릿에는 너비 150픽셀, 높이 150픽셀의 캔버스 개체가 있습니다. 오른쪽과 같이 화면에 기본 그리드를 겹쳐 놓았습니다. 일반적으로 그리드의 1단위는 캔버스의 1픽셀에 해당합니다. 그리드의 원점은 왼쪽 상단(좌표(0,0))에 위치합니다. 그림에 있는 모든 개체의 위치는 이 원점을 기준으로 합니다. 이런 식으로 왼쪽 위 모서리에 있는 파란색 사각형의 위치는 왼쪽에서 x 픽셀, 위쪽에서 Y 픽셀(좌표(x, y))입니다. 이후 튜토리얼에서는 원점을 이동하고 메시를 회전하고 크기를 조정하는 방법을 배웁니다. 하지만 지금은 기본 상태를 사용하겠습니다.
도형 그리기
캔버스는 하나의 기본 도형인 직사각형만 지원하므로 다른 도형은 하나 이상의 경로로 구성됩니다. 다행히도 매우 복잡한 모양을 그릴 수 있는 일련의 경로 그리기 기능이 있습니다.
직사각형
먼저 직사각형을 살펴보겠습니다. 직사각형을 그리는 데는 세 가지 함수가 있습니다.
fillRect(x,y,width,height) : Draws a filled rectangle strokeRect(x,y,width,height) : Draws a rectangular outline clearRect(x,y,width,height) : Clears the specified area and makes it fully transparent
모두 x와 y의 4개 매개변수를 받습니다. 직사각형의 왼쪽 위 모서리(원점을 기준으로), 너비와 높이는 직사각형의 너비와 높이입니다. 좋습니다. 한번 시도해 보겠습니다.
직사각형 그리기 예직사각형 모양 예
function draw(){ var canvas = document.getElementById('tutorial'); if (canvas.getContext){ var ctx = canvas.getContext('2d'); ctx.fillRect(25,25,100,100); ctx.clearRect(45,45,60,60); ctx.strokeRect(50,50,50,50); } }
결과는 위와 동일해야 합니다. 이하. fillRect
함수는 큰 검정색 직사각형(100x100)을 그리고,clearRect
함수는 중앙의 60x60 정사각형을 지운 다음, 스트로크Rect
함수는 비워진 공간에 50x50 직사각형 테두리의 윤곽을 그립니다. 다음 페이지에서는clearRect
함수와 유사한 두 가지 다른 메서드와 그래픽의 채우기 및 테두리 색상을 변경하는 방법을 살펴보겠습니다.
경로 그리기 경로 그리기
직사각형 그리기와 달리 경로 그리기에는 몇 가지 추가 단계가 필요합니다.
beginPath() closePath() stroke() fill()
첫 번째 단계는 BeginPath
를 사용하여 경로를 만드는 것입니다. 메모리에서 경로는 함께 그래픽을 형성하는 하위 경로 집합(선, 호 등)의 형태로 저장됩니다. BeginPath
가 호출될 때마다 하위 경로 그룹이 재설정되고 새 그래픽을 그릴 수 있습니다.
두 번째 단계는 곧 살펴보겠지만 경로를 실제로 그리는 것입니다.
세 번째 단계는 closePath
메서드를 호출하는 것입니다. 이 메서드는 현재 끝점과 시작 끝점을 직선으로 연결하여 경로를 닫으려고 시도하지만 모양이 이미 닫혀 있거나 단 한 점만 있어도 아무 일도 일어나지 않습니다. 이 단계는 필요하지 않습니다.
마지막 단계는 획이나 채우기 메서드를 호출하는 것입니다. 이때 실제로 그래픽이 캔버스에 그려집니다. 획은 그래픽을 그리는 데 사용되는 테두리이며, 채우기는 이를 통해 단색 그래픽을 채웁니다.
참고: fill이 호출되면 closePath를 호출하지 않고 열린 경로가 자동으로 닫힙니다.
삼각형 등 간단한 도형을 그리는 코드는 다음과 같습니다.
ctx.beginPath(); ctx.moveTo(75,50); ctx.lineTo(100,75); ctx.lineTo(100,25); ctx.fill();
moveTo
는 아무것도 그리는 데 사용할 수 없지만 경로를 그리는 실용적인 방법의 일부입니다. 펜을 들어 올려 한 지점에서 다른 지점으로 이동하는 것으로 생각할 수 있습니다. x
및 y(새 좌표 위치)를 매개변수로 허용합니다. 캔버스가 초기화되거나 BeginPath가 호출될 때 시작 좌표 설정은 원점(0,0)입니다. 대부분의 경우 시작 좌표를 다른 위치로 이동하거나 불연속적인 경로를 그릴 때 moveTo 메서드를 사용합니다. 아래 웃는 얼굴을 보세요. 빨간색 선은 moveTo를 사용하여 이동한 궤적입니다.
ctx.beginPath(); ctx.arc(75,75,50,0,Math.PI*2,true); // Outer circle ctx.moveTo(110,75); ctx.arc(75,75,35,0,Math.PI,false); // Mouth (clockwise) ctx.moveTo(65,65); ctx.arc(60,65,5,0,Math.PI*2,true); // Left eye ctx.moveTo(95,65); ctx.arc(90,65,5,0,Math.PI*2,true); // Right eye ctx.stroke(); ctx.beginPath(); ctx.moveTo(40,75); ctx.lineTo(60,65); ctx.lineTo(90,65); ctx.moveTo(110,75); ctx.lineTo(125,75); ctx.stroke();
我们用lineTo方法来画直线。lineTo方法接受终点的坐标(x,y)作为参数。起始坐标取决于前一路径,前一路径的终点即当前路径的起点,起始坐标也可以通过moveTo方法来设置。示例(如下图)画的是两个三角形,一个实色填充,一个勾边。首先调用beginPath方法创建一个新路径,然后用moveTo方法将起始坐标移至想要的位置,然后画两条直线来构成三角形的两条边。
// 填充三角形 ctx.beginPath(); ctx.moveTo(25,25); ctx.lineTo(105,25); ctx.lineTo(25,105); ctx.fill(); // 勾边三角形 ctx.beginPath(); ctx.moveTo(125,125); ctx.lineTo(125,45); ctx.lineTo(45,125); ctx.closePath(); ctx.stroke();
弧线 Arcs
我们用arc方法来绘制弧线或圆。标准说明中还包含arcTo方法,当前 Safari 是支持的,但基于 Gecko 的浏览器还未实现。方法接受五个参数:x,y 是圆心坐标,radius 是半径,startAngle和endAngle分别是起末弧度(以 x 轴为基准),anticlockwise为 true 表示逆时针,反之顺时针。警告:在 Firefox 的 beta 版本里,最后一个参数是clockwise,而最终版本不是。因此如果是从 beta 升级至发行版需要做相应修改。
注意:arc方法里用到的角度是以弧度为单位而不是度。度和弧度直接的转换可以用这个表达式:var radians = (Math.PI/180)*degrees;。
arc(x, y, radius, startAngle, endAngle, anticlockwise)
arc
的使用示例
这个示例比之前见到过的要复杂一些,画了12个不同的弧形,有不同夹角和填充状态的。如果我用上面画笑脸的方式来画这些弧形,那会是一大段的代码,而且, 画每一个弧形时我都需要知道其圆心位置。像我这里画 90,180 和 270 度的弧形看起来不是很麻烦,但是如果图形更复杂一些,则实现起来会越来越困难。这里使用两个for
循环来画多行多列的弧形。每一个弧形都用beginPath方法创建一个新路径。然后为了方便阅读和理解,我把所有参数都写成变量形式。显而易见,x 和 y 作为圆心坐标。radius和startAngle都是固定,endAngle从 180 度半圆开始,以 90 度方式递增至圆。anticlockwise则取决于奇偶行数。最后,通过 if语句判断使前两行表现为勾边,而后两行为填充效果。
for (i=0;i<4;i++){ for(j=0;j<3;j++){ //chinese_xu 原始代码 ctx.beginPath(); var x = 25+j*50; // x coordinate var y = 25+i*50; // y coordinate var radius = 20; // Arc radius var startAngle = 0; // Starting point on circle var endAngle = Math.PI+(Math.PI*j)/2; // End point on circle ---//修复错误标点 var anticlockwise = i%2==0 ? false : true; // clockwise or anticlockwise ctx.arc(x,y,radius,startAngle,endAngle, anticlockwise); if (i>1){ ctx.fill(); } else { ctx.stroke(); } } } //chinese_xu 原始代码并没有按照1/4圆递增来画。 //修改后输出4行4列,要把画布扩大到200*200观看 for (i=0;i<4;i++){ for(j=0;j<4;j++){ ctx.beginPath(); var x = 25+j*50; // x coordinate var y = 25+i*50; // y coordinate var radius = 20; // Arc radius var startAngle = 0; // Starting point on circle var endAngle = Math.PI*(2-j/2); // End point on circle var anticlockwise = i%2==0 ? false : true; // clockwise or anticlockwise ctx.arc(x,y,radius,startAngle,endAngle, anticlockwise); if (i>1){ ctx.fill(); } else { ctx.stroke(); } } }
以上就是canvas游戏开发学习之二:绘制基本图形的内容,更多相关内容请关注PHP中文网(m.sbmmt.com)!