FingerEyes-Xr에서 파이 차트(Pie Chart) 표현하기

지도 상에 통계 데이터를 차트를 통해 표현하는 코드를 정리해 봅니다. 차트의 종류는 많지만 이중 지도와 가장 잘맞는 차트는 파이 차트인데요. 이 파이 차트를 표시해 보도록 하겠습니다.

먼저 차트를 표시할 수치지도 레이어를 추가합니다. 차트 표시를 위해 반드시 수치지도가 필요한 것은 아니지만.. 수치지도는 차트를 표시할 위치와 통계 데이터를 속성 값으로 가질 수 있으므로 차트에 대한 예제로 사용하기에 좋습니다. 아래의 코드는 수치지도를 표시하는 코드입니다.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />

    <style>
        body {
            margin: 0px;
            padding: 0px;
        }

        #map {
            top: 0px;
            left: 0px;
            position: absolute;
            width: 100%;
            height: 100%;
            border: none;
            outline: none;
        }
    </style>

    <script src="../../scripts/fingereyes-xr/Xr.js">

    <script>
        var map = null;

        function onLoad() {
            map = new Xr.Map("map", {});

            var lyr = new Xr.layers.ShapeMapLayer("lyr",
                {
                    url: "http://168.192.76.10:8080/Xr?layerName=li_a@test"
                }
            );
            
            var theme = lyr.theme();
            theme.penSymbol().color("black");
            theme.brushSymbol().color("lightgray");
            lyr.needAttribute(true);

            var lm = map.layers();
            lm.add(lyr);

            map.onLayersAllReady(onLayersReady);

            window.addEventListener("resize", onResize);
        }

        var bFinishResizing = true;

        function onResize() {
            if (bFinishResizing) {
                bFinishResizing = false;

                setTimeout(function () {
                    var newWidth = window.innerWidth;
                    var newHeight = window.innerHeight;

                    map.resize(newWidth, newHeight);
                    map.update();

                    bFinishResizing = true;
                }, 500);                
            }
        }

        function onLayersReady() {
            var cm = map.coordMapper();
            var lyr = map.layers("lyr");
            var mbr = lyr.MBR();

            cm.zoomByMBR(mbr);

            map.update();
        }
    </script>

    <title></title>
</head>

<body onload="onLoad()">
    <div id="map" />
</body>
</html>

위의 코드에서 중요한 부분은 40번째 코드에서 수치지도 레이어에 대한 속성값이 필요하다고 명시하고 있다는 점입니다. 차트 표시를 위한 통계값으로써 수치지도의 속성값이 필요하므로 이 코드가 필요합니다. 만약 수치지도 레이어가 라벨 표시를 사용한다면 자동으로 속성값을 호출하므로 굳이 이 코드가 필요하지는 않습니다. 이제 버튼을 올려두고 이 버튼을 클릭했을때 차트를 지도 상에 표시하는 코드를 작성해 보도록 하겠습니다.

이제 이 수치지도에 차트를 구성하는 코드를 작성할 것인데요. 아래의 doCharting 함수가 차트를 구성합니다.

 function doCharting() {
    var gl = new Xr.layers.GraphicLayer("chart");
    map.layers().add(gl);

    var graphicRows = gl.rowSet();
    var lyr = map.layers("lyr");
    var rows = lyr.shapeRowSet().rows();
    var ars = lyr.attributeRowSet();
    var fieldSet = lyr.fieldSet();
    var idx_sum_po_u65 = fieldSet.fieldIndex("sum_po_u65");
    var idx_sum_po_u75 = fieldSet.fieldIndex("sum_po_u75");
    var minValue = Number.MAX_VALUE;
    var maxValue = -Number.MAX_VALUE;
            
    for (var fid in rows) {
        var aRow = ars.row(fid);
        var val_sum_po_u65 = aRow.valueAsFloat(idx_sum_po_u65);
        var val_sum_po_u75 = aRow.valueAsFloat(idx_sum_po_u75);
        var total = val_sum_po_u65 + val_sum_po_u75;

        if (minValue > total) minValue = total;
        if (maxValue < total) maxValue = total;
    }

    var graphMaxSize = 80;
    var graphMinSize = 30;

    for (var fid in rows) {
        var aRow = ars.row(fid);
        var sRow = rows[fid];
        var pt = sRow.shapeData().representativePoint();
        var val_sum_po_u65 = aRow.valueAsFloat(idx_sum_po_u65);
        var val_sum_po_u75 = aRow.valueAsFloat(idx_sum_po_u75);
        var totalValue = val_sum_po_u65 + val_sum_po_u75;
        var radiusOut = (((graphMaxSize - graphMinSize) * totalValue / (maxValue - minValue)) + graphMinSize) / 2;
        var pcisd = new Xr.data.PieChartItemShapeData({
            x: pt.x, y: pt.y,
            values: [val_sum_po_u65, val_sum_po_u75],
            radiusOut: radiusOut, radiusIn: radiusOut * 0.4
        });

        var pcigr = new Xr.data.PieChartItemGraphicRow(fid, pcisd);
        graphicRows.add(pcigr);

        pcigr.penSymbol().color("#ffffff").width(1);
        pcigr.brushSymbol(0).opacity(1).color('#1abc9c');
        pcigr.brushSymbol(1).opacity(1).color('#34495e');
    }

    gl.refresh();
}

위의 코드를 하나씩 살펴보면... 먼저 1-2번 코드는 chart라는 이름의 그래픽 레이어를 추가하고 있습니다. 바로 이 그래픽 레이어에 차트가 표현됩니다. 그리고 10번-11번에서는 2개의 필드에 대한 인덱스값을 저장하고 있습니다. doCharting 함수는 2개의 속성값을 이용해 파이차트를 구성하고 있는데, 이때 사용하는 필드는 sum_po_u65와 sum_po_u7 이고 그 값을 얻기 위해 필드 인덱스값이 필요합니다. 15번-23번 코드는 차트를 구성하는 값의 최대값과 최소값을 계산합니다. 25-26번은 파이 차트를 그릴때 최대값에서의 차트 크기와 최소값에서의 차트 크기를 나타냅니다. 차트 크기의 단위는 px입니다. 28번-48번이 그래픽 레이어에 차트 그래픽 요소를 추가하는 함수인데요. 차트 그래픽 요소를 구성하는 값들로써 차트가 표시될 위치, 값에 대한 배열, 차트의 크기가 있습니다. 이 함수를 실행하면 다음과 같은 결과 화면을 볼 수 있습니다.

FingerEyes-Xr에서 폰트(Font)를 이용한 마커 심벌(Marker Symbol) 지정하기

FingerEyes-Xr에서 포인트 타입의 수치지도는 다양한 형태로 표현될 수 있습니다. 원이나 사각형과 같은 단순 도형에서 이미지나 폰트를 통한 텍스트 표현까지 가능합니다. 특히 이미지는 애니메이션 GIF인 경우 애니메이션 효과도 그대로 표현됩니다.

이 글은 포인트 타입의 수치지도를 폰트를 통한 텍스트 표현을 위한 API에 대한 내용을 정리한 글입니다.

포인트를 폰트를 통한 텍스트로 표현하는 이유 중에 하나는 웹에서 딩벳(Dingbat) 폰트에서 일반적이지 않은 특별하게 디자인된 텍스트로 포인트 심벌을 표현하기 위함입니다. 아래의 화면은 멘홀에 대한 단순한 포인트를 하수설비에 대해 특별이 만들어진 폰트로 표현된 지도입니다.

노란색의 채움과 빨간색의 외곽선으로 표시된 아이콘 모양의 심벌이 바로 포인트 수치지도에 대해 표현된 텍스트인데요. 이처럼 수치지도 레이어에 폰트 심벌을 적용하는 코드는 아래와 같습니다.

var SB101 = new Xr.layers.ShapeMapLayer("SB101", {
    url: "http://168.192.76.10:8080/Xr?layerName=SB101"
});

var theme = SB101.theme();

var marker = new Xr.symbol.TextMarkerSymbol();
marker.text('1'); // Dingbat은 1이지만, 1이 아닌 뭔가 특별한 모양의 문자로 표시된다.

theme.markerSymbol(marker);

marker.fontSymbol().fontFamily("ffHasu").color("#ffff00").strokeColor("#ff0000").strokeWidth(3).size(36);

lm.add(SB101);

위의 코드 중 12번 코드에 fontFamily 함수를 통해 “ffHasu” 값을 지정하고 있습니다. 이 “ffHasu” 아래의 style을 통해 정의된 값입니다. 추가적으로 폰트가 사용자의 PC에 설치되어 있지 않을 경우, 웹에서 해당 폰트를 내려받아 웹페이지에서 사용할 수 있는데요. 아래의 코드는 특정 폰트를 내려받아 사용할 수 있도록 있도록 해주기도 합니다.

@font-face {
    font-family: ffHasu;
    src: url(../css/Hist_Hasu.woff);
}