[OpenLayers3] 지도 상에 포인트 마커 표시 및 클릭

배경지도 위의 원하는 위치에 마커를 표시하고, 표시된 마커를 클릭하면 저장된 속성을 표시하는 내용에 대해 살펴보겠습니다. 먼저 아래의 웹 페이지를 살펴보시기 바랍니다.

먼저 필요한 외부 css와 js 파일을 포함하는 코드를 추가합니다.




다음은 UI 코드인데요. 아래처럼 지도를 표시하는 div 하나가 필요합니다.

다음은 스크립트 코드입니다. 웹페이지가 로딩되고 준비가 완료되면 호출되는 jQuery의 ready 이벤트를 아래처럼 준비합니다.

$(function () {
    ....
});

위의 코드 중 …에 앞으로 설명하는 코드를 추가합니다. 먼저 배경지도 위에 표시될 마커에 대한 Feature 변수를 정의해야 하는데요. Feature는 Geometry와 Attribute로 구성됩니다. 아래처럼 iconFeature라는 변수로 정의합니다.

var iconFeature = new ol.Feature({
    geometry: new ol.geom.Point([0, 0]),
    name: '보이지 않는 꿈의 섬',
    population: 4000,
    rainfall: 500
});

위의 코드는 좌표 (0, 0)인 ol.geom.Point 타입의 지오메트리와 name, population, rainfall 속성을 갖는 Feature를 정의하고 있습니다. 다음은 이 Feature를 아이콘으로 표시할 스타일을 정의할 객체 변수입니다.

var iconStyle = new ol.style.Style({
    image: new ol.style.Icon(/** @type {olx.style.IconOptions} */({
        anchor: [0.5, 46],
        anchorXUnits: 'fraction',
        anchorYUnits: 'pixels',
        src: 'https://openlayers.org/en/v3.19.1/examples/data/icon.png'
    }))
});

위의 코드는 src로 지정된 url의 png 이미지로 포인트를 표시하며, 표시될때의 (X, Y)에 대한 기준점으로 (0.5, 46)으로 하는데요. X 축에 대한 값인 0.5의 단위를 anchorXUnits 속성을 통해 백분률(여기서는 0.5이므로 50%)로 지정하고, Y 축에 대한 값인 46의 단위는 anchorYUnits 속성을 통해 픽셀 단위로 지정한다는 의미입니다. 이렇게 하면 아이콘의 뽑족한 밑단이 정확히 가로로 가운데에 표시되게 됩니다. 이렇게 정의된 스타일을 해당 피쳐에 지정되도록 아래의 코드를 실행합니다.

iconFeature.setStyle(iconStyle);

Feature는 ol.source.Vector 클래스 타입의 데이터 소스로부터 담겨져 레이어가 필요로 하는 데이터를 제공하는데요. 아래처럼 데이터 소스와 이 데이터 소스를 이용하는 벡터 레이어 객체를 각각 정의합니다.

var vectorSource = new ol.source.Vector({
    features: [iconFeature]
});

var vectorLayer = new ol.layer.Vector({
    source: vectorSource
});

위의 코드 중 2번을 보면 데이터 소스 객체를 정의할때 features 속성에 앞서 정의한 Feature 객체를 배열의 요소로 담고 있습니다. 다음 코드는 배경맵을 위한 레이어 객체 정의입니다.

var rasterLayer = new ol.layer.Tile({
    source: new ol.source.TileJSON({
        url: 'https://api.tiles.mapbox.com/v3/mapbox.geography-class.json?secure',
        crossOrigin: ''
    })
});

이제 지도 객체를 생성하기 위한 필요한 모든 것이 준비되었는데요. 아래처럼 지도 객체를 생성합니다.

var map = new ol.Map({
    layers: [rasterLayer, vectorLayer],
    target: document.getElementById('map'),
    view: new ol.View({
        center: [0, 0],
        zoom: 3
    })
});

여기까지하면 배경지도 위에 우리가 표시하고자 하는 마커가 원하는 위치에 원하는 아이콘 이미지로 표시됩니다. 이제 이 아이콘을 클릭하면 피쳐에 저장된 속성 중 name의 값을 alert 창으로 표시하는 코드를 아래처럼 작성합니다.

map.on('click', function (evt) {
    var feature = map.forEachFeatureAtPixel(evt.pixel,
        function (feature) {
            return feature;
        });
        
    if (feature) {
        alert(feature.get('name'));
    }
});

클릭한 좌표는 evt.pixel로 얻을 수 있습니다. 이 evt.pixel의 값을 map의 forEachFeatureAtPixel 함수의 첫번재 인자로 전달하면 해당 클릭 좌표에 존재하는 피쳐를 forEachFeatureAtPixel의 두번째 인자로 지정한 함수가 호출되며, 이때 이 호출되는 함수의 인자로 피쳐의 객체가 전달됩니다. 4번 처럼 이 피쳐 객체를 그대로 반환하여 우리가 클릭한 피쳐를 얻을 수 있습니다. 7번에서 클릭한 지점에 feature 객체가 있다면 feature의 name 속성의 값을 alert 창으로 표시합니다.

여기서 한가지 더 추가하여, 우리가 어떤 아이콘을 클릭하기 전에 이 아이콘을 클릭하면 어떤 정보가 제공될것이라는 피드백(Feedback)을 제공하면 더욱 좋을 것인데요. 아래의 코드를 통해 이러한 피드백 효과를 제공할 수 있습니다.

map.on('pointermove', function (e) {
    if (!e.dragging) {
        var pixel = map.getEventPixel(e.originalEvent);
        var hit = map.hasFeatureAtPixel(pixel);
        map.getTarget().style.cursor = hit ? 'pointer' : '';
    }
});

지도를 이동하는 마우스 Dragging이 아닌 경우에 현재 마우스의 좌표 지점에 어떤 피쳐가 존재하는지를 검사해서 만약 마우스 커서 위치에 피쳐가 있다면 마우스 커서를 ‘pointer’ 타입으로 변경하도록 하면 앞서 언급한 피드백이 완성됩니다.

위는 이제까지 작성한 소스 코드의 다운로드입니다.

답글 남기기

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