[OpenLayers] 공간 데이터에 대한 Cluster 시각화

아래와 같은 위치를 표시하는 포인트 레이어가 있다.

이때 이 무수히 많은 포인트를 군집화해서(Clustering) 표현하면 아래와 같은 결과를 볼 수 있다.

일정한 거리를 기준으로 군집화, 즉 그룹으로 묶어서 묶여진 개수와 함께 표시하고 있다. 표시 속도 역시 빠르다. 이러한 공간 데이터에 대한 Cluster 시각화를 OpenLayers에서 구현하는 API에 대해 정리하는 글이다.

먼저 DOM 요소를 생성한데, 지도에 대한 div와 군집화를 위한 거리값을 입력 받기 위한 DOM이며 아래와 같다.



    
        
        OpenLayers
        
    

    

JS 코드는 index.js에서 작성되데, 먼저 OpenLayers 즉, ol에서 필요로 하는 모듈을 아래처럼 추가한다.

import Feature from 'ol/Feature.js';
import Map from 'ol/Map.js';
import View from 'ol/View.js';
import Point from 'ol/geom/Point.js';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer.js';
import {Cluster, OSM, Vector as VectorSource} from 'ol/source.js';
import {Circle as CircleStyle, Fill, Stroke, Style, Text} from 'ol/style.js';

다음은 필요한 변수를 정의한다.

var distance = document.getElementById('distance');

var count = 20000;
var features = new Array(count);
var e = 4500000;

distance 변수는 군집화를 위한 거리값을 입력받는 DOM 요소이고, count는 군집화 대상이 되는 포인트 개수이다. 그리고 features는 군집화 대상이 되는 포인트에 대한 Feature이다. Feature는 좌표값과 속성값을 갖으며 VectorSource의 구성 요소이다. e는 군집화 대상이 되는 포인트의 위치를 무작위로 결정하기 위한 범위값이다. 아래는 군집화 대상이 되는 포인트 Feature를 생성하는 코드이다.

for (var i = 0; i < count; ++i) {
    var coordinates = [2 * e * Math.random() - e, 2 * e * Math.random() - e];
    features[i] = new Feature(new Point(coordinates));
}

이렇게 생성된 Feature들에 대한 데이터 소스와 Cluster 데이터 소스를 아래처럼 생성한다.

var source = new VectorSource({
    features: features
});

var clusterSource = new Cluster({
    distance: parseInt(distance.value, 10),
    source: source
});

지도의 구성 요소로써 화면에 표시되기 위해 레이어가 필요하며, 데이터소스는 레이어를 생성하는데 이용된다. 앞서 생성한 데이터소스를 아래의 코드처럼 활용하여 레이어를 생성한다.

var styleCache = {};
var clusters = new VectorLayer({
    source: clusterSource,
    style: function(feature) {
        var size = feature.get('features').length;
        var style = styleCache[size];
    
        if (!style) {
            style = new Style({
                image: new CircleStyle({
                    radius: 10,
                    stroke: new Stroke({
                        color: '#fff'
                    }),
                    fill: new Fill({
                        color: '#3399CC'
                    })
                }),
                text: new Text({
                    text: size.toString(),
                    fill: new Fill({
                        color: '#fff'
                    })
                })
            });
    
            styleCache[size] = style;
        }

        return style;
    }
});

아래의 코드처럼 지도를 생성하고 앞서 생성된 레이어를 지도의 구성 요소로 정의한다. 배경지도로써 OpenStreetMap도 또 다른 레이어로 활용했다.

var raster = new TileLayer({
    source: new OSM()
});

var map = new Map({
    layers: [raster, clusters],
    target: 'map',
    view: new View({
        center: [0, 0],
        zoom: 2
    })
});

마지막으로 클러스터를 위한 거리값 지정을 위한 DOM에 아래와 같은 이벤트를 추가하여 언제든 사용자가 거리값을 변경하여 클러스터링에 반영할 수 있도록 한다.

distance.addEventListener('input', function() {
    clusterSource.setDistance(parseInt(distance.value, 10));
});

이제 실행하면 그 결과를 볼 수 있다.

답글 남기기

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