[Project] Realtime Interactive Web Charts and Graphics #1. Start

PC 윈도우에서 Visual C#의 GDI (Graphical Devic Interface) Class와 Graphics Library를 이용하여 Chart가 있는 프로그램을 개발할 수 있습니다. 하지만 웹에서 실시간 상호작용이 가능한 Chart를 구현하는 것은 쉽지 않습니다. 물론 상용 라이브러리도 있고, 잘 찾아보면 Open Source도 있을 수 있지만,  직접 만들어보고 윈도우 애저(Windows Azure)에 기반한 웹사이트를 만들어 보고자 합니다.

아래는 각각 Windows 프로그램과 Web에서의 그림을 그리는 방법에 대한 간단한 예제입니다.

■ [PC Windows] Visual C# + GDI Class + Graphics Library

protected override void OnPaint(PaintEventArgs e)    
{    
    Graphics g = e.Graphics;        
    // Draw a line from (0, 0) to (1, 2) in unit of inch    
    g.PageUnit = GraphicsUnit.Inch;   
    Pen blackPen = new Pen(Color.Black, 1 / g.DpiX);           
    g.DrawLine(blackPen, 0, 0, 1, 2); 
}

■ [Web Pages] HTML + JavaScript <canvas> + SignalR

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8"/>
  <script type="application/javascript">
    function draw() {
      var canvas = document.getElementById("canvas");
      if (canvas.getContext) {
        var ctx = canvas.getContext("2d");

        ctx.fillStyle = "rgb(200,0,0)";
        ctx.fillRect (10, 10, 50, 50);

        ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
        ctx.fillRect (30, 30, 50, 50);
      }
    }
  </script>
 </head>
 <body onload="draw();">
   <canvas id="canvas" width="150" height="150"></canvas>
 </body>
</html>

상기 코드는 잘 알려져 있는 것들이고 본 프로젝트에서는 웹용 2D Chart를 그리는 JavaScript와 Realtime Interactive한 웹을 가능하게 하는 SignalR을 결합하는 것이 목적입니다.
우선 먼저 Graphics의 기본 사항에 대해 이야기 해봅시다.

■ Coordinate Systems: <canvas>의 좌표계는 아래 두 그림과 같이 수학에서 배우는 Chart와 많이 다릅니다. 따라서 좌표 변환 함수가 필요합니다.

  1. Default Canvas Coordinates
    DefaultCanvasCoordinate
  2. 2D Chart를 위한 Custom Coordinates
    CustomCoordinates
다음은 500x500 Size의 캔버스에 Offset 20를 주고 (xMin, yMin)= (20, 0), (xMax, yMax)=(100, 50)를 만족하는 좌표에 세 개의 점을 그리는 HTML+JavaScript 코드입니다.

scaleFactor 변수와 point2D 함수를 정의하였고, 그외 Canvas 관련 함수는 MDN(Mozilla Developer Network)의 Canvas API 웹사이트를 참고하시기 바랍니다.

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>MathWell1EX1: Draw Coordinates</title>
<script type="text/javascript">
window.addEventListener("load", eventWindowLoaded, false);
function eventWindowLoaded() { canvasApp(); }

function canvasApp() {
    var theCanvas = document.getElementById("canvasOne");
    if (!theCanvas || !theCanvas.getContext) { return; }
    var context = theCanvas.getContext("2d");
    
    var offset = 20;
    var pMin = {x:20, y:0};
    var pMax = {x:100, y:50};
    var scaleFactor = {x:(theCanvas.width-2*offset)/(pMax.x - pMin.x),
        y:(theCanvas.height-2*offset)/(pMax.y - pMin.y)};
        
    function point2D(point) {
        var retpnt = {x:(point.x - pMin.x)*scaleFactor.x + offset,
            y:(theCanvas.height - (point.y- pMin.y)*scaleFactor.y) - offset};
        return retpnt;
    }
    
    var points = new Array();
    points.push(point2D({x:50, y:30}));
    points.push(point2D(pMin));
    points.push(point2D(pMax));
    
    function drawScreen() {
        //Background
        context.fillStyle = "#EEEEEE";
        context.fillRect(0, 0, theCanvas.width, theCanvas.height);
        //Box
        context.strokeStyle = "#000000";
        context.strokeRect(offset, offset, theCanvas.width-2*offset,
            theCanvas.height-2*offset);

        //Points
        for (var i = 0; i <points.length; i++) {
            context.fillStyle = "#FF0000";
            context.beginPath();
            context.arc(points[i].x, points[i].y, 5, 0, Math.PI * 2, true);
            context.closePath();
            context.fill();
        }
    }
    
    drawScreen();
}
</script>
</head>
<body>
<div style="position: absolute; top: 50px; left: 50px;">
<canvas id="canvasOne" width="500" height="500">
Your browser does not support HTML5 Canvas. 
</canvas>
</div>
</body>
</html>

다음은 캔버스 내에서 움직이는 공을 나타내는 코드를 짜 보려고 합니다.

댓글