[그래픽 처리] 그래프 렌더링/꺽은선 그래프/모눈종이
꺽은선 그래프를 렌더링하는 프로그램에 대해 설명하기 전에 먼저 캔버스에 기준선을 렌더링 해보겠습니다.
[1] 모눈종이(눈금) 렌더링
배경을 그라데이션으로 렌더링한 후, 가로선과 세로선을 렌더링합니다.
for 문을 이용해 선긋기를 반복합니다.
캔버스의 width속성, height속성을 이용해 캔버스 크기에 맞춰 렌더링 합니다.
10x10dml 모눈종이를 나타내기 위해 'grid_cols'와 'grid_rows' 값을 10으로 지정했습니다.
for문을 통해 'col'이 'grid_cols' 값인 10 보다 작을 때 col에 하나씩 더해져 10까지 반복하게 합니다.
'row'도 마찬가지겠죠.
그리고
'cell_height'은 height속성을 이용해 a_canvas.height/grid_rows(10이겠죠.)로 셀의 높이를 지정하고,
'var x = col*cell_height' 수식으로 col 값에 셀 높이를 곱해 눈금이 생성되게 합니다.
셀 너비도 마찬가지겠죠.
[2] 꺽은선 그래프 렌더링
어떤 상품의 매출 데이터(12개월/단위: 백만원)를 꺽은선 그래프로 나타내보겠습니다.
데이터는 아래와 같다고 봅니다.
1월 | 2월 | 3월 | 4월 | 5월 | 6월 | 7월 | 8월 | 9월 | 10월 | 11월 | 12월 |
80 | 92 | 104 | 110 | 68 | 50 | 45 | 90 | 74 | 68 | 98 | 103 |
매출 데이터를 그래프의 좌표로 나타내기 위해 먼저 데이터의 최대값을 조사한 후 , 이 최대값을 기준으로 렌더링할 값의 좌표를 계산했습니다.
코드가 길어서 주석을 이용해 코드에 대해 설명하도록 하겠습니다.
//먼저 데이터를 준비합니다.
var uriage=[80,92,104,110,68,50,45,90,74,68,98,103];
drawChart(uriage);
var uriage=[80,92,104,110,68,50,45,90,74,68,98,103];
drawChart(uriage);
//컨텍스트를 얻고은 후 배경을 렌더링 합니다.
var gradient=context.createLinearGradient(0,0,0,300);
gradient.addColorStop(0, "#e0e0e0"); //시작 지점의 인수를 0으로 지정해 제일 위에 회색을 띄고
gradient.addColorStop(1, "#ffffff"); //아래로 갈수록 흰색이 나오게 그라데이션 했습니다..
context.fillStyle=gradient;
context.fillRect(0,0,a_canvas.width,a_canvas.height);
var gradient=context.createLinearGradient(0,0,0,300);
gradient.addColorStop(0, "#e0e0e0"); //시작 지점의 인수를 0으로 지정해 제일 위에 회색을 띄고
gradient.addColorStop(1, "#ffffff"); //아래로 갈수록 흰색이 나오게 그라데이션 했습니다..
context.fillStyle=gradient;
context.fillRect(0,0,a_canvas.width,a_canvas.height);
//좌표
var grid_cols=data.length+1; //데이터의 수에 따라 col 달라집니다.
var grid_rows=4; //grid_row 값을 4로 지정하고 보조선 렌더링 위해 for문을 사용해 고정시킵니다.
var cell_width=a_canvas.width/grid_cols;
var cell_height=a_canvas.height/grid_rows;
var grid_cols=data.length+1; //데이터의 수에 따라 col 달라집니다.
var grid_rows=4; //grid_row 값을 4로 지정하고 보조선 렌더링 위해 for문을 사용해 고정시킵니다.
var cell_width=a_canvas.width/grid_cols;
var cell_height=a_canvas.height/grid_rows;
//배경의 보조선 렌더링
context.beginPath();
for (var row=0; row<=grid_rows; row++){ // 데이터 수가 달라져도 row수는 4로 고정이 되겠죠.
var y = row*cell_height;
context.moveTo(0,y);
context.lineTo(a_canvas.width,y);
}
for (var col=0; col<=grid_cols; col++){ // 데이터 수가 달라지면 col 수 도 달라집니다.
var x = col*cell_width;
context.moveTo(x, 0);
context.lineTo(x, a_canvas.height);
}
context.lineWidth=1;
context.strokeStyle="#c0c0c0"; // 보조선의 색을 지정
context.stroke();
context.beginPath();
for (var row=0; row<=grid_rows; row++){ // 데이터 수가 달라져도 row수는 4로 고정이 되겠죠.
var y = row*cell_height;
context.moveTo(0,y);
context.lineTo(a_canvas.width,y);
}
for (var col=0; col<=grid_cols; col++){ // 데이터 수가 달라지면 col 수 도 달라집니다.
var x = col*cell_width;
context.moveTo(x, 0);
context.lineTo(x, a_canvas.height);
}
context.lineWidth=1;
context.strokeStyle="#c0c0c0"; // 보조선의 색을 지정
context.stroke();
//데이터의 최대값을 먼저 조사합니다.
var max_v=0; //max_v에는 좌표의 최대값이 저장되어 있습니다.
for(var i=0; i<data.length; i++){
if (data[i]>max_v) max_v = data[i];
}
//최대값이 그래프를 벗어나지 않도록 값을 가산합니다.
max_v=max_v*1.1;
var max_v=0; //max_v에는 좌표의 최대값이 저장되어 있습니다.
for(var i=0; i<data.length; i++){
if (data[i]>max_v) max_v = data[i];
}
//최대값이 그래프를 벗어나지 않도록 값을 가산합니다.
max_v=max_v*1.1;
//데이터 플롯용 좌표
var points=[];
for(var i=0; i<data.length; i++){
var v=data[i];
var px=cell_width*(i+1);
var py=a_canvas.height-a_canvas.height*(v/max_v);
points.push({"x":px, "y":py});
/**그래픽 좌표는 화면의 가장 위가 0, 아래로 내려갈수록 값이 커집니다.
구한 좌표(px,py)를 배열 변수 points에 추가합니다.
좌표를 배열 변수에 저장해 두는 이유는, **/
}
var points=[];
for(var i=0; i<data.length; i++){
var v=data[i];
var px=cell_width*(i+1);
var py=a_canvas.height-a_canvas.height*(v/max_v);
points.push({"x":px, "y":py});
/**그래픽 좌표는 화면의 가장 위가 0, 아래로 내려갈수록 값이 커집니다.
구한 좌표(px,py)를 배열 변수 points에 추가합니다.
좌표를 배열 변수에 저장해 두는 이유는, **/
}
//선 그래프를 렌더링
context.beginPath(); //먼저 각 좌표들을 선으로 연결한 후,
context.moveTo(points[0].x, points[0].y);
for(var i=1; i<points.length; i++){
context.lineTo(points[i].x, points[i].y);
}
context.lineWidth=2;
context.strokeStyle="Yellow"; //선은 노란색으로 지정했습니다.
context.stroke();
context.beginPath(); //먼저 각 좌표들을 선으로 연결한 후,
context.moveTo(points[0].x, points[0].y);
for(var i=1; i<points.length; i++){
context.lineTo(points[i].x, points[i].y);
}
context.lineWidth=2;
context.strokeStyle="Yellow"; //선은 노란색으로 지정했습니다.
context.stroke();
//좌표 플롯
for(var i in points){ //각 좌표에 원을 그리기 위해서입니다.
var p=points[i];
context.beginPath();
context.arc(p.x,p.y,6,0,2*Math.PI);
context.fillStyle="#ee0000"; //원(점)은 빨강입니다.
context.fill();
}
for(var i in points){ //각 좌표에 원을 그리기 위해서입니다.
var p=points[i];
context.beginPath();
context.arc(p.x,p.y,6,0,2*Math.PI);
context.fillStyle="#ee0000"; //원(점)은 빨강입니다.
context.fill();
}
총 종합한 코드의 모습입니다.
데이터의 수에 따라 col의 수가 달라지는 것을 확인해보세요.
데이터 수가 달라져도 row수는 변화하지 않습니다.
저는 아래와 같이 데이터를 변경해 보았습니다.
var uriage=[1,2,3,4,3,2,1]; | var uriage=[10,2,7]; |
'HTML5' 카테고리의 다른 글
[그래픽 처리] 변형 행렬의 저장과 복구/회전/save()/restore()/rotate() (0) | 2012.02.10 |
---|---|
[그래픽 처리] 변형 행렬의 이동과 확대/축소/translate()/scale() (0) | 2012.02.10 |
[그래픽 처리] 변형 행렬 메서드/setTransform()/transform()/rotate()/scale()/translate()/save()/restore() (0) | 2012.02.10 |
[그래픽 처리] 그림 파일 렌더링/drawImage() (0) | 2012.02.09 |
[그래픽 처리] 컨텍스트(Context)의 속성 (0) | 2012.02.09 |
[그래픽 처리] 그라데이션(gradation)/createLinearGradient()/CreateRadialGradient() (0) | 2012.02.09 |
[그래픽 처리] 렌더링 메서드/arc(), arcTo()/quadraticCurveTo(), bezieCurveTo()/rect() (0) | 2012.02.09 |