✨ Intro
🚀 목표
Vue.js에서 오픈레이어스의 기본 지도인 OSM(Open Street Map) 띄우기
⚙️ 환경
Vue3(v 3.5.13) + Composition API + setup
✨ 프로젝트 생성 및 라이브러리 설치
vite로 vue 프로젝트를 생성해준다.
npm create vite@latest
vite 설치 가이드 : https://ko.vite.dev/guide/
프로젝트 생성 후 아래 명령어를 통해 vue 프로젝트로 경로 이동 후 node-modules를 설치 해준다.
cd 프로젝트명
npm install
오픈레이어스를 설치한다.
npm i ol
✨ OpenLayers로 지도 띄우기
src 폴더 밑에 composables 폴더를 생성한다. Composable은 Vue 3의 Composition API를 사용할 때, 코드의 재사용성과 모듈화를 높이기 위해 만든 재사용 가능한 함수이다.
컴포저블 : https://v3-docs.vuejs-korea.org/guide/reusability/composables.html
useMap.ts
- 지도를 생성하는 함수를 별도로 분리했다.
- 배경으로 기본 레이어인 OSM을 추가했다.
// src/composables/useMap.js
import { onMounted, ref } from "vue";
import "ol/ol.css";
import Map from "ol/Map";
import View from "ol/View";
import TileLayer from "ol/layer/Tile";
import OSM from "ol/source/OSM";
/**
* OpenLayers 지도를 초기화하는 커스텀 훅
*/
export function useMap() {
const mapContainer = ref<HTMLDivElement | null>(null); // DOM 요소를 위한 ref
const mapInstance = ref<Map | null>(null); // Map 인스턴스의 타입 지정
onMounted(() => {
if (!mapContainer.value) return;
mapInstance.value = new Map({
target: mapContainer.value,
layers: [
new TileLayer({
source: new OSM(),
}),
],
view: new View({
center: [0, 0], // EPSG:3857 좌표계 기준
zoom: 2, // 초기 줌 레벨
}),
});
});
return {
mapContainer, // Vue 템플릿에서 참조할 div 요소
mapInstance, // 필요 시 지도 객체 활용 가능
};
}
MapView.vue
- 지도 생성 함수를 사용해 div에 지도를 표출한다.
- width와 heigth를 제대로 설정하지 않으면 지도가 표시되지 않는다.
// src/components/MapView.vue
<script setup>
import { useMap } from "../composables/useMap";
const { mapContainer } = useMap();
</script>
<template>
<div class="map-wrapper">
<div ref="mapContainer" class="map-container"></div>
</div>
</template>
<style scoped>
.map-wrapper {
width: 100vw;
height: 100vh; /* 부모 요소의 높이를 명확하게 설정 */
}
.map-container {
width: 100%;
height: 100%;
}
</style>
App.vue
app에 MapView 컴포넌트를 로드한다.
// src/App.vue
<script setup lang="ts">
import MapView from "./components/MapView.vue";
</script>
<template>
<MapView />
</template>
<style scoped></style>
여백 제거하기
지도가 표출되는데 여백이 존재한다. style.css에서 padding과 max-width를 제거해준다
// src/style.css
#app {
/* max-width: 1280px; */
margin: 0 auto;
/* padding: 2rem; */
text-align: center;
}
지도가 화면 꽉차게 표시된다.
🗺️ 좌표계 변경하기(선택사항) - EPSG:5179로 변경
OpenLayers는 EPSG:3857을 기본 좌표계로 사용한다. 우리 나라는 다른 보통 다른 좌표계를 사용하는데 EPSG:3857 외에 다른 좌표계가 필요할 경우 아래와 같은 방법으로 변경 가능하다.
좌표계 변환을 위해 proj4와 @types/proj4을 설치 해준다.
proj4란?
지도 제작 투영 간의 변환을 수행하기 위한 라이브러리이다.
npm i proj4 @types/proj4
useMap.ts - EPSG:5179 좌표계 적용
- projection 상수를 정의하고 openlayers에 등록 해준다.
- View에서 좌표계, zoom Level, 센터 좌표등을 정해준다.
import { onMounted, ref } from "vue";
import "ol/ol.css";
import Map from "ol/Map";
import View from "ol/View";
import TileLayer from "ol/layer/Tile";
import OSM from "ol/source/OSM";
import proj4 from "proj4";
import { register } from "ol/proj/proj4";
/**
* OpenLayers 지도를 초기화하는 커스텀 훅
*/
export function useMap() {
const mapContainer = ref<HTMLDivElement | null>(null); // DOM 요소를 위한 ref
const mapInstance = ref<Map | null>(null); // Map 인스턴스의 타입 지정
const EPSG_5179_PROJECTION =
"+proj=tmerc +lat_0=38 +lon_0=127.5 +k=0.9996 +x_0=1000000 +y_0=2000000 +ellps=GRS80 +units=m +no_defs";
onMounted(() => {
if (!mapContainer.value) return;
proj4.defs("EPSG:5179", EPSG_5179_PROJECTION); // EPSG 좌표계 정의
register(proj4); // Proj4 좌표계를 OpenLayers에 등록
mapInstance.value = new Map({
target: mapContainer.value,
layers: [
new TileLayer({
source: new OSM(),
}),
],
view: new View({
projection: "EPSG:5179",
center: [953955.030189, 1952075.661092], // 5179 기준 서울 중심점
zoom: 8.7, // 초기 줌 레벨
}),
});
});
return {
mapContainer, // Vue 템플릿에서 참조할 div 요소
mapInstance, // 필요 시 지도 객체 활용 가능
};
}
좌표계 목록
EPSG:5179 좌표계 외에 다른 좌표계가 필요한 경우 아래와 같이 인터넷에서 필요한 좌표계의 projection을 찾아 사용하면 된다. 간혹 자료마다 projection이 상이할 수 있으니 반드시 테스트가 필요하다.
/**
* EPSG:3857 / EPSG:900913 / EPSG:102113
* 오픈레이어스(OpenLayers)에 기본 탑재되어 있는 좌표계로 추가 등록 필요 없음
* 네이버(v5), 구글맵, VWorld지도에서 사용
* TM 방식의 좌표계가 아니므로 거리 측정에 사용할 수 없는 좌표계
*/
export const EPSG_3857_PROJECTION =
"+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs";
/**
* EPSG:4326
* WGS84 타원체의 경위도 좌표계
* GPS 등의 기본 좌표계
*/
export const EPSG_4326_PROJECTION = "+proj=longlat +datum=WGS84 +no_defs";
/**
* EPSG:5179
* GRS80 타원체의 UTM-K 직각 좌표계
* 네이버(v3)와 도로명주소 DB에서 사용하는 좌표계
*/
export const EPSG_5179_PROJECTION =
"+proj=tmerc +lat_0=38 +lon_0=127.5 +k=0.9996 +x_0=1000000 +y_0=2000000 +ellps=GRS80 +units=m +no_defs";
/**
* ESPG:5181
* GRS80 타원체의 한국 중부원점, Y 축으로 500000미터만큼 이동시킨 좌표계
* 카카오 맵에서 사용하는 좌표계
*/
export const EPSG_5181_PROJECTION =
"+proj=tmerc +lat_0=38 +lon_0=127 +k=1 +x_0=200000 +y_0=500000 +ellps=GRS80 +units=m +no_defs";
/**
* EPSG:5186
* GRS80 타원체의 한국 중부원점, Y 축으로 600000미터만큼 이동시킨 좌표계
*/
export const EPSG_5186_PROJECTION =
"+proj=tmerc +lat_0=38 +lon_0=127 +k=1 +x_0=200000 +y_0=600000 +ellps=GRS80 +units=m +no_defs";
🔰 완성
중심점을 서울로 설정 및 EPSG:3857→EPSG:5179 좌표계까지 적용한 지도이다.
Zoom Level을 축소 시 우리나라를 중심으로 지도가 둥글게 변형된 것을 확인할 수 있다.
'OpenLayers' 카테고리의 다른 글
[OpenLayers] vue-query를 활용하여 지도 레이어 가져오기 (1) | 2025.02.18 |
---|---|
[Openlayers] 지도 기본 컨트롤러 숨기기 (0) | 2024.06.13 |
[OpenLayers] 지도 확대 축소시 겹치는 text 안보이게 하기 - Declutter (0) | 2023.10.24 |
[Openlayers] hover시 원하는 레이어에 선택하여 속성 표출하기(pointermove) (0) | 2023.08.03 |