[Openlayers5] 2.배경지도 변경 버튼 추가하기
#1 레이어란?
레이어는 지도를 구성하는 핵심 요소 중 하나입니다.
레이어는 지도에 표시되는 지리적 데이터를 나타냅니다.
이 데이터는 다양한 형태로 표현될 수 있으며, 주로 지도 배경, 지리적 특성, 마커, 선,
다각형 등의 요소로 구성됩니다.
레이어는 OpenLayers에서 중요한 개념이며, 지도 애플리케이션을 개발할 때
지리적 데이터를 효과적으로 관리하고 표현하기 위해 사용됩니다.
#2 레이어 그룹이란?
레이어 그룹은 레이어를 구성하고 관리하기 위한 개념입니다.
레이어 그룹은 여러 레이어를 하나의 그룹으로 묶어서 관리할 수 있도록 도와주며,
주로 시각적 관리, 가시성 제어, 레이어 순서, 이벤트 관리의 목적으로 사용됩니다.
#3 시작하기
<!DOCTYPE html>
<html>
<head>
<!-- OpenLayers 5 라이브러리 추가 -->
<script src="../js/lib/openlayers/v5.3.3-dist/ol.js"></script>
<link rel="stylesheet" href="../css/openlayers/v5.3.3-dist/ol.css" type="text/css">
<style>
/* 지도를 표시할 div 요소의 스타일 설정 */
#map {
width: 100%;
height: 600px;
}
.ctlBaseMapBtns {
position: absolute;
right: 10px;
bottom : 10px;
}
</style>
<script>
var mainMap = null;
//============================[ util S ]============================
/**
* 특정 베이스 맵 레이어를 화면에서 표시하거나 숨기는 함수입니다.
*
* @param {string} layerName - 표시하려는 베이스 맵 레이어의 이름.
* @example
* // 베이스 맵 레이어 이름이 "osm"인 경우를 활성화
* fn_visibleBaseMap("osm");
*
* // 베이스 맵 레이어 이름이 "vworld"인 경우를 활성화
* fn_visibleBaseMap("vworld");
*/
function fn_visibleBaseMap(layerName) {
// 'grpBaseMap' 레이어 그룹 찾기
var grpBaseMapLayers = mainMap.getLayers().getArray().find(function (ly) {
return ly.get("name") == "grpBaseMap";
});
// 'grpBaseMap' 그룹 내의 레이어 순회
grpBaseMapLayers.getLayers().getArray().forEach(function (ly) {
// 주어진 레이어 이름과 현재 레이어의 이름 비교
if(ly.get("name") == layerName) {
// 주어진 레이어를 표시
ly.setVisible(true);
} else {
// 다른 레이어는 숨김
ly.setVisible(false);
}
});
}
//============================[ util E ]============================
window.onload = function() {
// EPSG:3857 좌표계 정의
var proj3857 = new ol.proj.Projection({
code: 'EPSG:3857',
extent: [-20037508.34, -20037508.34, 20037508.34, 20037508.34],
units: 'm'
});
// 타일 레이어 추가 (OpenStreetMap 사용)
var baseMapOsm = new ol.layer.Tile({
//타일 레이어의 이름을 osm으로 지정
name: "osm",
// 타일 레이어의 데이터 원천 설정 (OpenStreetMap 사용)
source: new ol.source.OSM(),
//타일 레이어의 순서를 지정한다.(높을수록 먼저 보인다.)
zIndex: 1,
// 타일 레이어를 처음부터 보이게 설정(true, false)
visible: false,
// 사전 로드 타일 레벨 설정
preload: 16,
// 레이어의 투명도 설정 (1은 완전 불투명, 0은 완전 투명)
opacity: 1
});
// V-World 위성 지도 타일 레이어 생성
var baseMapVworld = new ol.layer.Tile({
// 타일 레이어의 이름을 "vworld"로 지정
name : "vworld",
// 타일 레이어의 데이터 원천 설정 (XYZ 타일 소스 사용)
source : new ol.source.XYZ({
// 비공식(라이센스 위반, 라이센스 미필요) URL (주석 처리된 부분)
// url: "https://xdworld.vworld.kr/2d/Satellite/service/{z}/{x}/{y}.jpeg",
// V-World 위성 지도 타일 서비스 URL (라이센스를 준수하는 공식 URL)
url: "http://api.vworld.kr/req/wmts/1.0.0/라이센스키/Satellite/{z}/{y}/{x}.jpeg",
}),
// 타일 레이어의 순서를 지정한다. (높을수록 먼저 보인다.)
zIndex : 1,
// 타일 레이어를 처음부터 보이게 설정(true, false)
visible : true,
// 사전 로드 타일 레벨 설정
preload: 16,
// 레이어의 투명도 설정 (1은 완전 불투명, 0은 완전 투명)
opacity: 1
});
// 타일 레이어 그룹 생성
var baseMapGroup = new ol.layer.Group({
// 타일 레이어의 이름을 "grpBaseMap"로 지정
name: "grpBaseMap",
// 이 그룹에 속할 레이어들을 배열로 나열
layers: [baseMapOsm, baseMapVworld]
});
// 맵 객체 생성
mainMap = new ol.Map({
// 지도가 표시될 div 요소의 id 설정
target: 'map',
// 레이어 추가 (타일 레이어 그룹 추가)
layers: [baseMapGroup],
// 뷰 설정
view: new ol.View({
// 중심 좌표 설정 (위도, 경도)
center: ol.proj.transform([126, 37], 'EPSG:4326', 'EPSG:3857'),
// 줌 레벨 설정 (1~20 사이의 정수)
zoom: 8,
// 좌표계 설정
projection: proj3857
})
});
// 컨트롤을 생성하고 HTML 버튼 요소를 사용하여 초기화
var mapBtnBaseMapVworld = new ol.control.Control({
// HTML 버튼을 가져올 요소의 id 지정
element : document.getElementById("btnBaseMaps")
});
// 생성한 컨트롤을 메인 지도에 추가
mainMap.addControl(mapBtnBaseMapVworld);
}
</script>
</head>
<body>
<!-- 지도를 표시할 div 요소 추가 -->
<div id="map" class="map"></div>
<!-- 지도의 배경지도를 제어할 div 요소 추가 -->
<div>
<button id="btnVworld" onclick="fn_visibleBaseMap('vworld')">vworld</button>
<button id="btnOsm" onclick="fn_visibleBaseMap('osm')" >osm</button>
</div>
<div id="btnBaseMaps" class="ctlBaseMapBtns">
<button id="btnCtlVworld" onclick="fn_visibleBaseMap('vworld')">ctl_vworld</button>
<button id="btnCtlOsm" onclick="fn_visibleBaseMap('osm')" >ctl_osm</button>
</div>
</body>
</html>
#4 소스 설명
.ctlBaseMapBtns {
position: absolute;
right: 10px;
bottom : 10px;
}
지도 위에 올릴 div 요소의 스타일을 설정합니다.
//============================[ util S ]============================
/**
* 특정 베이스 맵 레이어를 화면에서 표시하거나 숨기는 함수입니다.
*
* @param {string} layerName - 표시하려는 베이스 맵 레이어의 이름.
* @example
* // 베이스 맵 레이어 이름이 "osm"인 경우를 활성화
* fn_visibleBaseMap("osm");
*
* // 베이스 맵 레이어 이름이 "vworld"인 경우를 활성화
* fn_visibleBaseMap("vworld");
*/
function fn_visibleBaseMap(layerName) {
// 'grpBaseMap' 레이어 그룹 찾기
var grpBaseMapLayers = mainMap.getLayers().getArray().find(function (ly) {
return ly.get("name") == "grpBaseMap";
});
// 'grpBaseMap' 그룹 내의 레이어 순회
grpBaseMapLayers.getLayers().getArray().forEach(function (ly) {
// 주어진 레이어 이름과 현재 레이어의 이름 비교
if(ly.get("name") == layerName) {
// 주어진 레이어를 표시
ly.setVisible(true);
} else {
// 다른 레이어는 숨김
ly.setVisible(false);
}
});
}
//============================[ util E ]============================
유틸 함수 추가
사용자에게 주어진 베이스 맵 레이어의 이름에 따라 해당 레이어를 화면에서 표시하거나 숨기는 역할을 합니다.
먼저, 함수는 mainMap 지도 객체에서 'grpBaseMap' 레이어 그룹을 찾습니다.
그다음, 그룹 내의 모든 레이어를 순회하면서 주어진 layerName과 현재 레이어의 이름을 비교합니다.
만약 주어진 레이어의 이름과 현재 레이어의 이름이 일치하면 해당 레이어를 화면에 표시하도록 설정합니다.
그렇지 않으면 다른 레이어는 숨깁니다.
이 함수를 사용하면 특정 베이스 맵 레이어를 활성화하고 다른 레이어를 비활성화하여
지도의 베이스 맵을 변경할 수 있습니다.
// 타일 레이어 추가 (OpenStreetMap 사용)
var baseMapOsm = new ol.layer.Tile({
//타일 레이어의 이름을 osm으로 지정
name: "osm",
// 타일 레이어의 데이터 원천 설정 (OpenStreetMap 사용)
source: new ol.source.OSM(),
//타일 레이어의 순서를 지정한다.(높을수록 먼저 보인다.)
zIndex: 1,
// 타일 레이어를 처음부터 보이게 설정(true, false)
visible: false,
// 사전 로드 타일 레벨 설정
preload: 16,
// 레이어의 투명도 설정 (1은 완전 불투명, 0은 완전 투명)
opacity: 1
});
// V-World 위성 지도 타일 레이어 생성
var baseMapVworld = new ol.layer.Tile({
// 타일 레이어의 이름을 "vworld"로 지정
name : "vworld",
// 타일 레이어의 데이터 원천 설정 (XYZ 타일 소스 사용)
source : new ol.source.XYZ({
// 비공식(라이센스 위반, 라이센스 미필요) URL (주석 처리된 부분)
// url: "https://xdworld.vworld.kr/2d/Satellite/service/{z}/{x}/{y}.jpeg",
// V-World 위성 지도 타일 서비스 URL (라이센스를 준수하는 공식 URL)
url: "http://api.vworld.kr/req/wmts/1.0.0/라이센스키/Satellite/{z}/{y}/{x}.jpeg",
}),
// 타일 레이어의 순서를 지정한다. (높을수록 먼저 보인다.)
zIndex : 1,
// 타일 레이어를 처음부터 보이게 설정(true, false)
visible : true,
// 사전 로드 타일 레벨 설정
preload: 16,
// 레이어의 투명도 설정 (1은 완전 불투명, 0은 완전 투명)
opacity: 1
});
이전 [Openlayers5] 1.시작하기 에서는 new ol.Map을 선언할 때 layers에 바로 넣었으나
소스의 길이가 길어지면서 변수로 분리하였습니다.
- name은 레이어의 고유한 이름이며, 레이어를 정확하게 식별하고 관리하는데 사용합니다.
- zIndex는 레이어의 겹침 순서를 제어합니다.
- visible은 레이어가 지도에 표시되는지 여부를 나타냅니다.
- preload은 사전 로드 타일 레벨을 설정합니다. 지도가 초기화될 때 미리 로드되는 타일 수를 나타냅니다.
- opacity은 레이어의 투명도를 설정합니다. 값이 1이면 완전히 불투명하고 0이면 완전히 투명합니다.
// 타일 레이어 그룹 생성
var baseMapGroup = new ol.layer.Group({
// 타일 레이어의 이름을 "grpBaseMap"로 지정
name: "grpBaseMap",
// 이 그룹에 속할 레이어들을 배열로 나열
layers: [baseMapOsm, baseMapVworld]
});
타일 레이어 그룹 생성
생성한 레이어들을 레이어 그룹에 추가합니다.
// 맵 객체 생성
mainMap = new ol.Map({
// 지도가 표시될 div 요소의 id 설정
target: 'map',
// 레이어 추가 (타일 레이어 그룹 추가)
layers: [baseMapGroup],
// 뷰 설정
view: new ol.View({
// 중심 좌표 설정 (위도, 경도)
center: ol.proj.transform([126, 37], 'EPSG:4326', 'EPSG:3857'),
// 줌 레벨 설정 (1~20 사이의 정수)
zoom: 8,
// 좌표계 설정
projection: proj3857
})
});
맵 객체에 그룹 레이어를 추가합니다.
// 컨트롤을 생성하고 HTML 버튼 요소를 사용하여 초기화
var mapBtnBaseMapVworld = new ol.control.Control({
// HTML 버튼을 가져올 요소의 id 지정
element : document.getElementById("btnBaseMaps")
});
// 생성한 컨트롤을 메인 지도에 추가
mainMap.addControl(mapBtnBaseMapVworld);
배경지도 변경 버튼을 Openlayers 컨트롤에 추가
만약 지도 밖에 버튼을 만들고 제어를 할 예정이면 컨트롤에 등록을 안 해도 괜찮습니다.
<!-- 지도의 배경지도를 제어할 div 요소 추가 -->
<div>
<button id="btnVworld" onclick="fn_visibleBaseMap('vworld')">vworld</button>
<button id="btnOsm" onclick="fn_visibleBaseMap('osm')" >osm</button>
</div>
<div id="btnBaseMaps" class="ctlBaseMapBtns">
<button id="btnCtlVworld" onclick="fn_visibleBaseMap('vworld')">ctl_vworld</button>
<button id="btnCtlOsm" onclick="fn_visibleBaseMap('osm')" >ctl_osm</button>
</div>
배경지도를 제어할 버튼 추가
id="btnBaseMaps"은 컨트롤에 추가하여 지도 안에 추가 할 버튼입니다.
위와 같이 지도 안에 추가된 버튼과 지도 밖에 있는 버튼이 생기며 클릭 시 배경화면이 변경됩니다.