vworld-react-3d
Version:
VWorld 3.0 API React Component - 한국 공공데이터 3D 지도 컴포넌트
356 lines (280 loc) • 11.1 kB
Markdown
# VWorld React 3D
한국 공공데이터 VWorld 3.0 API를 React에서 쉽게 사용할 수 있는 컴포넌트 패키지입니다.
## 🚀 설치
```bash
npm install vworld-react-3d
# 또는
yarn add vworld-react-3d
```
## 📖 사용법
### 기본 사용법
```tsx
import React from "react";
import { VWorldMap } from "vworld-react-3d";
function App() {
return (
<div>
<h1>VWorld 3D 지도</h1>
<VWorldMap
config={{ apiKey: "YOUR_VWORLD_API_KEY" }}
width="100%"
height="600px"
onMapReady={(map) => {
console.log("맵이 준비되었습니다:", map);
}}
onMapClick={(coord) => {
console.log("클릭 위치:", coord);
}}
/>
</div>
);
}
```
### 고급 사용법 (카메라 제어)
```tsx
import React, { useState, useRef } from "react";
import {
VWorldMap,
getGwanghwamunCameraPosition,
createCoordZ,
createDirection,
createCameraPosition,
} from "vworld-react-3d";
function App() {
const [mapInstance, setMapInstance] = useState(null);
const [cameraPosition, setCameraPosition] = useState(null);
// 서울타워로 이동
const moveToSeoulTower = () => {
const seoulTower = createCameraPosition(
createCoordZ(126.988, 37.551, 1000), // 경도, 위도, 고도
createDirection(0, -30, 0) // heading, pitch, roll
);
setCameraPosition(seoulTower);
};
// 부산으로 이동
const moveToBusan = () => {
const busan = createCameraPosition(
createCoordZ(129.075, 35.179, 2000),
createDirection(0, -45, 0)
);
setCameraPosition(busan);
};
return (
<div>
<VWorldMap
config={{ apiKey: "YOUR_VWORLD_API_KEY" }}
options={{
mapId: "vmap",
logo: true,
navigation: true,
backgroundColor: "#f0f0f0",
}}
initCameraPosition={getGwanghwamunCameraPosition(500)}
cameraPosition={cameraPosition}
width="100%"
height="500px"
onMapReady={(map) => {
console.log("맵 준비:", map);
setMapInstance(map);
}}
onMapClick={(coord) => {
console.log("클릭 위치:", coord);
}}
onCameraChange={(camera) => {
console.log("카메라 변경:", camera);
}}
/>
<div style={{ marginTop: "10px" }}>
<button onClick={moveToSeoulTower}>서울타워로 이동</button>
<button onClick={moveToBusan}>부산으로 이동</button>
</div>
</div>
);
}
```
### 맵 인스턴스 직접 제어
```tsx
import React, { useRef } from "react";
import { VWorldMap } from "vworld-react-3d";
function App() {
const mapRef = useRef(null);
const controlMap = () => {
if (mapRef.current) {
const map = mapRef.current;
// 현재 위치 가져오기
const currentPos = map.getCurrentPosition();
console.log("현재 위치:", currentPos);
// 새로운 위치로 이동
const newCoord = new window.vw.CoordZ(126.977, 37.571, 1000);
map.setPosition(newCoord);
}
};
return (
<div>
<VWorldMap
ref={mapRef}
config={{ apiKey: "YOUR_VWORLD_API_KEY" }}
width="100%"
height="500px"
onMapReady={(map) => {
console.log("사용 가능한 메서드:", Object.getOwnPropertyNames(map));
}}
/>
<button onClick={controlMap}>맵 제어</button>
</div>
);
}
```
## 🔑 API 키 발급
VWorld API 키는 [VWorld 개발자 포털](https://www.vworld.kr/dev/v4dv_opnkeyinfo_s001.do)에서 발급받을 수 있습니다.
## 📚 Props
### VWorldMapProps
| Prop | Type | Required | Default | Description |
| -------------------- | ---------------------------------------- | -------- | --------- | ----------------- |
| `config` | `VWorldConfig` | ✅ | - | VWorld API 설정 |
| `options` | `Partial<VWorldMapOptions>` | ❌ | `{}` | 맵 옵션 |
| `initCameraPosition` | `VWorldCameraPosition` | ❌ | 광화문 | 초기 카메라 위치 |
| `cameraPosition` | `VWorldCameraPosition` | ❌ | - | 동적 카메라 위치 |
| `zoom` | `number` | ❌ | - | 줌 레벨 |
| `onMapReady` | `(map: VWorldMapInstance) => void` | ❌ | - | 맵 준비 완료 콜백 |
| `onMapLoad` | `() => void` | ❌ | - | 맵 로드 완료 콜백 |
| `onCameraChange` | `(camera: VWorldCameraPosition) => void` | ❌ | - | 카메라 변경 콜백 |
| `onZoomChange` | `(zoom: number) => void` | ❌ | - | 줌 변경 콜백 |
| `onMapClick` | `(coord: VWorldCoord) => void` | ❌ | - | 맵 클릭 콜백 |
| `onMapDoubleClick` | `(coord: VWorldCoord) => void` | ❌ | - | 맵 더블클릭 콜백 |
| `onMouseMove` | `(coord: VWorldCoord) => void` | ❌ | - | 마우스 이동 콜백 |
| `onWheel` | `(delta: number) => void` | ❌ | - | 휠 스크롤 콜백 |
| `onError` | `(error: string) => void` | ❌ | - | 오류 발생 콜백 |
| `className` | `string` | ❌ | `''` | CSS 클래스명 |
| `style` | `React.CSSProperties` | ❌ | `{}` | 인라인 스타일 |
| `width` | `string \| number` | ❌ | `'100%'` | 컨테이너 너비 |
| `height` | `string \| number` | ❌ | `'600px'` | 컨테이너 높이 |
### VWorldConfig
| Property | Type | Required | Description |
| -------- | -------- | -------- | ------------- |
| `apiKey` | `string` | ✅ | VWorld API 키 |
### VWorldMapOptions
| Property | Type | Default | Description |
| -------------------- | --------- | ----------- | --------------------------- |
| `mapId` | `string` | `'vmap'` | 맵 컨테이너 ID |
| `logo` | `boolean` | `true` | 로고 표시 여부 |
| `navigation` | `boolean` | `true` | 네비게이션 컨트롤 표시 여부 |
| `autoRotate` | `boolean` | `false` | 자동 회전 여부 |
| `showGrid` | `boolean` | `false` | 그리드 표시 여부 |
| `showAxis` | `boolean` | `false` | 축 표시 여부 |
| `backgroundColor` | `string` | `'#000000'` | 배경색 |
| `terrain` | `boolean` | `true` | 지형 표시 여부 |
| `buildings` | `boolean` | `true` | 건물 표시 여부 |
| `roads` | `boolean` | `true` | 도로 표시 여부 |
| `water` | `boolean` | `true` | 물 표시 여부 |
| `vegetation` | `boolean` | `true` | 식생 표시 여부 |
| `enableAntialiasing` | `boolean` | `true` | 안티앨리어싱 활성화 |
| `enableShadows` | `boolean` | `true` | 그림자 활성화 |
| `maxFPS` | `number` | `60` | 최대 FPS |
## 🛠️ 유틸리티 함수
### 좌표 및 위치 생성
```tsx
import {
createCoord,
createCoordZ,
createDirection,
createCameraPosition,
getGwanghwamunCameraPosition,
} from "vworld-react-3d";
// 2D 좌표 생성
const coord2D = createCoord(126.977, 37.571);
// 3D 좌표 생성 (고도 포함)
const coord3D = createCoordZ(126.977, 37.571, 500);
// 방향 생성 (heading, pitch, roll)
const direction = createDirection(0, -45, 0);
// 카메라 위치 생성
const cameraPos = createCameraPosition(coord3D, direction);
// 광화문 위치 (고도 기반)
const gwanghwamun = getGwanghwamunCameraPosition(1000); // 1000m 고도
```
## 🎯 주요 기능
### ✅ 완전한 TypeScript 지원
- 모든 타입이 정확하게 정의됨
- IntelliSense 완벽 지원
### ✅ React 16.8+ 호환
- Hooks 기반 구현
- forwardRef 지원으로 맵 인스턴스 직접 접근 가능
### ✅ 자동 스크립트 로딩
- jQuery 자동 로드
- VWorld 3.0 API 자동 로드
- 순차적 스크립트 로딩으로 안정성 보장
### ✅ 64개 공식 API 메서드 지원
- 맵 초기화 및 제어
- 카메라 위치 및 방향 제어
- 줌 및 회전 제어
- 이벤트 처리
- 성능 최적화
### ✅ 이벤트 시스템
- 맵 준비/로드 이벤트
- 카메라 변경 이벤트
- 클릭/더블클릭 이벤트
- 마우스 이동/휠 이벤트
### ✅ 에러 처리
- 스크립트 로딩 실패 처리
- 맵 초기화 실패 처리
- 사용자 친화적 에러 메시지
## 🌐 브라우저 지원
- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+
## 📦 패키지 구조
```
vworld-react-3d/
├── dist/ # 빌드된 파일들
│ ├── index.esm.js # ES 모듈
│ ├── index.d.ts # TypeScript 타입 정의
│ └── index.js # CommonJS
├── src/
│ ├── VWorldMap.tsx # 메인 컴포넌트
│ ├── types.ts # TypeScript 타입 정의
│ ├── utils.ts # 유틸리티 함수
│ └── index.ts # 진입점
├── package.json
├── rollup.config.mjs # 빌드 설정
└── README.md
```
## 🔧 개발
```bash
# 의존성 설치
npm install
# 개발 모드 (파일 감시)
npm run dev
# 빌드
npm run build
# 타입 체크
npm run type-check
# 린트
npm run lint
```
## 📄 라이선스
MIT License
## 🤝 기여하기
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
## 🐛 문제 신고
버그나 기능 요청이 있으시면 [GitHub Issues](https://github.com/kimgh06/vworld-react-3d/issues)에 등록해주세요.
## 📝 변경 이력
### 3.0.0
- 🎯 **VWorld 3.0 API 완전 지원** (64개 메서드)
- 🎮 **카메라 제어 기능** (위치, 방향, 줌)
- 📡 **완전한 이벤트 시스템** (클릭, 카메라 변경, 마우스 등)
- 🛠️ **유틸리티 함수** (좌표 생성, 위치 관리)
- 🔧 **forwardRef 지원** (맵 인스턴스 직접 접근)
- 📚 **완전한 TypeScript 타입 정의**
### 2.0.0
- 🚀 **성능 최적화**
- 🔧 **빌드 시스템 개선**
- 📦 **ES 모듈 지원**
### 1.0.0
- 🎉 **초기 릴리스**
- 🗺️ **기본 VWorld 3D 맵 컴포넌트**
- 📱 **React 16.8+ 지원**