FingerEyes-Xr에서 속성값에 따라 라벨 텍스트에 대한 그리기 심벌 변경하기

일반적으로는 하나의 레이어에 대해서 라벨에 대한 텍스트는 하나의 심벌로 통일해서 아래처럼 표시합니다.

위에 화면에 대한 소스 코드(코드A)는 아래와 같습니다.

<!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"
                }
            );
            
            // Label Setting           
            var label = lyr.label();
            label.enable(true);
            label.formatter().fieldName("first_nv_n");
            label.theme().symbol().size(40).strokeWidth(5);
            // .

            var theme = lyr.theme();
            theme.penSymbol().color("black").width(3);
            theme.brushSymbol().color("lightgray");

            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>

그러나 속성값에 따라 라벨 텍스트의 그리기 심벌을 달리해야 할 필요가 있을 수 있는데요. 예를 들어 인구수에 따라 라벨의 글자 색상을 변경하거나 폰트의 크기를 변경하여 표현할 수 있습니다. 이를 위해서는 다음과 같은 클래스의 정의가 필요합니다.

CustomLabelTheme = Xr.Class({
    name: "CustomLabelTheme",
    extend: Xr.theme.ProgrammableLabelDrawTheme,
    requires: [Xr.theme.ILabelDrawTheme],

    construct: function (/* ShapeMapLayer */ layer) {
        this.superclass(layer);

        this._fieldIndex = -1;

        var minValue = 13;
        var maxValue = 104;
        var stepCount = 5;
        var stepValue = (maxValue - minValue) / stepCount;
        var colors = ['#f1c40f', '#f39c12', '#e67e22', '#e74c3c', '#c0392b'];
        var sizes = [20, 25, 30, 40, 50];
        var symbols = [];

        for (var i = 0; i < stepCount; i++) {
            var FS = new Xr.symbol.FontSymbol();
            FS.color(colors[i]).size(sizes[i]).strokeWidth(sizes[i]/10);
                    
            var symbol = {
                fromValue: minValue + (i * stepValue),
                toValue: minValue + ((i + 1) * stepValue),
                symbol: FS
            };

            symbols[i] = symbol;
        }

        this._symbols = symbols;
        this._stepCount = stepCount;
    },

    methods: {
        /* FontSymbol */ symbol: function (/* ShapeRow */ shapeRow, /* FieldSet */ fieldSet, /* AttributeRow */ attributeRow) {
            if (this._fieldIndex === -1) {
                this._fieldIndex = fieldSet.fieldIndex("sum_ho_res");
            }

            var value = attributeRow.valueAsString(this._fieldIndex);
            var stepCount = this._stepCount;
            var symbols = this._symbols;
            var symbol = undefined;

            for (var i = 0; i < stepCount; i++) {
                symbol = symbols[i];

                if (value >= symbol.fromValue && value < symbol.toValue) {
                    break;
                }
            }

            return symbol.symbol;
        },

        /* boolean */ needAttribute: function () {
            return true;
        }
    }
});

위의 CustomLabelTheme 클래스는 표시할 라벨의 텍스트의 심벌을 속성값에 따라 변경할 수 있는 기능을 제공하며, 이를 위해서 Xr.theme.ProgrammableLabelDrawTheme 클래스를 상속하고 Xr.theme.ILabelDrawTheme 인터페이스를 구현해야 합니다. 이 클래스의 생성자에서는 라벨 텍스트의 표시를 위해 사용할 폰트 심벌을 미리 생성해 두고 있습니다. 폰트 심벌의 생성 규칙은 속성값의 최대값과 최소값을 이미 알고 있다고 할때(11번과 12번 코드에 매직넘버로 심어 두었지만 실제 적용시에는 이러한 최대, 최소값은 DBMS의 Query를 통해 얻어야 함), 이 값의 범위를 5개의 구간으로 구분하고 각 구간에 대해서 텍스트의 색상과 크기를 이용하여 폰트 심벌을 미리 정의해 배열에 담고 두고 있습니다. 그리고 라벨을 실제로 그릴때 사용할 폰트의 심벌을 얻기 위해서는 symbol 함수가 실행되어 폰트 심벌이 반환되는데요. symbol 함수를 살펴보면, 속도 향상을 위해 폰트 심벌을 결정할 필드의 인덱스를 계산해 두고, 해당 필드값을 이용해 생성자에서 미리 생성해 두었던 5개의 폰트 심벌 중 하나를 선택해 반환하고 있습니다. 이 클래스를 적용하기 위해서는 코드A의 41번 코드 대신 아래의 코드로 대체해야 합니다.

var newTheme = new CustomLabelTheme(lyr);            
label.theme(newTheme);

이제 실행 결과에 대한 이미지를 살펴보면 다음과 같습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다