search for the most current information about implementing Korean maps with jVectorMap.
by 개발자   2025-06-05 10:24:27   조회수:21

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Interactive Korea Map</title>
   
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            padding: 20px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
        }
       
        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            border-radius: 15px;
            box-shadow: 0 20px 40px rgba(0,0,0,0.1);
            padding: 30px;
        }
       
        .header {
            text-align: center;
            margin-bottom: 30px;
        }
       
        .header h1 {
            color: #333;
            margin: 0;
            font-size: 2.5rem;
            font-weight: 300;
        }
       
        .header p {
            color: #666;
            font-size: 1.1rem;
            margin: 10px 0 0 0;
        }
       
        .map-container {
            position: relative;
            height: 600px;
            border: 2px solid #e0e0e0;
            border-radius: 10px;
            overflow: hidden;
            margin-bottom: 20px;
            background: #f8f9fa;
        }
       
        #koreaMap {
            width: 100%;
            height: 100%;
        }
       
        .controls {
            display: flex;
            justify-content: center;
            gap: 15px;
            margin-bottom: 20px;
            flex-wrap: wrap;
        }
       
        .btn {
            background: linear-gradient(45deg, #667eea, #764ba2);
            color: white;
            border: none;
            padding: 12px 24px;
            border-radius: 25px;
            cursor: pointer;
            font-size: 14px;
            font-weight: 500;
            transition: transform 0.2s, box-shadow 0.2s;
        }
       
        .btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(102, 126, 234, 0.3);
        }
       
        .btn:active {
            transform: translateY(0);
        }
       
        .region {
            fill: #e3f2fd;
            stroke: #ffffff;
            stroke-width: 2;
            cursor: pointer;
            transition: all 0.3s ease;
        }
       
        .region:hover {
            fill: #1976d2;
            fill-opacity: 0.8;
            transform: scale(1.02);
        }
       
        .region.selected {
            fill: #0d47a1;
        }
       
        .region.population-low { fill: #FEF0D9; }
        .region.population-medium { fill: #FDCC8A; }
        .region.population-high { fill: #FC8D59; }
        .region.population-very-high { fill: #D7301F; }
       
        .region.economic-low { fill: #F0F9E8; }
        .region.economic-medium { fill: #BAE4BC; }
        .region.economic-high { fill: #7BCCC4; }
        .region.economic-very-high { fill: #2B8CBE; }
       
        .tooltip {
            position: absolute;
            background: rgba(0, 0, 0, 0.8);
            color: white;
            padding: 10px;
            border-radius: 5px;
            font-size: 14px;
            pointer-events: none;
            z-index: 1000;
            opacity: 0;
            transition: opacity 0.3s;
        }
       
        .info-panel {
            background: #f8f9fa;
            border-radius: 10px;
            padding: 20px;
            margin-top: 20px;
        }
       
        .info-panel h3 {
            margin: 0 0 15px 0;
            color: #333;
        }
       
        .region-info {
            display: none;
            background: white;
            border: 1px solid #ddd;
            border-radius: 8px;
            padding: 15px;
            margin-top: 10px;
        }
       
        .legend {
            display: flex;
            justify-content: center;
            gap: 20px;
            margin-top: 15px;
            flex-wrap: wrap;
        }
       
        .legend-item {
            display: flex;
            align-items: center;
            gap: 8px;
            font-size: 14px;
        }
       
        .legend-color {
            width: 20px;
            height: 20px;
            border-radius: 3px;
            border: 1px solid #ccc;
        }
       
        .region-label {
            font-family: 'Segoe UI', sans-serif;
            font-size: 12px;
            fill: #333;
            text-anchor: middle;
            pointer-events: none;
            font-weight: 500;
        }
       
        @media (max-width: 768px) {
            .container {
                padding: 20px;
                margin: 10px;
            }
           
            .header h1 {
                font-size: 2rem;
            }
           
            .map-container {
                height: 500px;
            }
           
            .region-label {
                font-size: 10px;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>대한민국 지도</h1>
            <p>Interactive map of South Korea with regional data visualization</p>
        </div>
       
        <div class="controls">
            <button class="btn" onclick="showPopulation()">인구 데이터</button>
            <button class="btn" onclick="showEconomic()">경제 지표</button>
            <button class="btn" onclick="resetMap()">초기화</button>
            <button class="btn" onclick="zoomToSeoul()">서울 확대</button>
        </div>
       
        <div class="map-container">
            <svg id="koreaMap" viewBox="0 0 800 600">
                <!-- Seoul -->
                <path id="seoul" class="region" d="M380,180 L420,180 L420,200 L400,220 L380,200 Z" data-name="서울특별시" data-code="KR-11"/>
               
                <!-- Gyeonggi -->
                <path id="gyeonggi" class="region" d="M320,140 L480,140 L480,240 L420,240 L420,200 L380,200 L380,220 L320,220 Z" data-name="경기도" data-code="KR-41"/>
               
                <!-- Incheon -->
                <path id="incheon" class="region" d="M280,160 L320,160 L320,200 L280,200 Z" data-name="인천광역시" data-code="KR-28"/>
               
                <!-- Gangwon -->
                <path id="gangwon" class="region" d="M480,100 L650,100 L650,280 L550,280 L520,250 L480,240 Z" data-name="강원도" data-code="KR-42"/>
               
                <!-- Chungcheongbuk -->
                <path id="chungbuk" class="region" d="M400,240 L520,240 L520,320 L400,320 Z" data-name="충청북도" data-code="KR-43"/>
               
                <!-- Chungcheongnam -->
                <path id="chungnam" class="region" d="M280,240 L400,240 L400,340 L280,340 Z" data-name="충청남도" data-code="KR-44"/>
               
                <!-- Daejeon -->
                <path id="daejeon" class="region" d="M360,280 L400,280 L400,300 L360,300 Z" data-name="대전광역시" data-code="KR-30"/>
               
                <!-- Jeollabuk -->
                <path id="jeonbuk" class="region" d="M280,340 L450,340 L450,420 L280,420 Z" data-name="전라북도" data-code="KR-45"/>
               
                <!-- Jeollanam -->
                <path id="jeonnam" class="region" d="M200,420 L450,420 L450,520 L200,520 Z" data-name="전라남도" data-code="KR-46"/>
               
                <!-- Gwangju -->
                <path id="gwangju" class="region" d="M320,440 L360,440 L360,460 L320,460 Z" data-name="광주광역시" data-code="KR-29"/>
               
                <!-- Gyeongsangbuk -->
                <path id="gyeongbuk" class="region" d="M520,200 L650,200 L650,380 L520,380 L520,320 Z" data-name="경상북도" data-code="KR-47"/>
               
                <!-- Daegu -->
                <path id="daegu" class="region" d="M520,320 L560,320 L560,350 L520,350 Z" data-name="대구광역시" data-code="KR-27"/>
               
                <!-- Gyeongsangnam -->
                <path id="gyeongnam" class="region" d="M450,380 L650,380 L650,480 L450,480 Z" data-name="경상남도" data-code="KR-48"/>
               
                <!-- Busan -->
                <path id="busan" class="region" d="M600,440 L650,440 L650,480 L600,480 Z" data-name="부산광역시" data-code="KR-26"/>
               
                <!-- Ulsan -->
                <path id="ulsan" class="region" d="M580,380 L620,380 L620,410 L580,410 Z" data-name="울산광역시" data-code="KR-31"/>
               
                <!-- Jeju -->
                <path id="jeju" class="region" d="M250,540 L350,540 L350,580 L250,580 Z" data-name="제주특별자치도" data-code="KR-49"/>
               
                <!-- Region Labels -->
                <text x="400" y="195" class="region-label">서울</text>
                <text x="400" y="175" class="region-label">경기</text>
                <text x="300" y="185" class="region-label">인천</text>
                <text x="565" y="190" class="region-label">강원</text>
                <text x="460" y="285" class="region-label">충북</text>
                <text x="340" y="295" class="region-label">충남</text>
                <text x="380" y="295" class="region-label">대전</text>
                <text x="365" y="385" class="region-label">전북</text>
                <text x="325" y="475" class="region-label">전남</text>
                <text x="340" y="455" class="region-label">광주</text>
                <text x="585" y="295" class="region-label">경북</text>
                <text x="540" y="340" class="region-label">대구</text>
                <text x="550" y="435" class="region-label">경남</text>
                <text x="625" y="465" class="region-label">부산</text>
                <text x="600" y="400" class="region-label">울산</text>
                <text x="300" y="565" class="region-label">제주</text>
            </svg>
        </div>
       
        <div class="legend" id="legend">
            <div class="legend-item">
                <div class="legend-color" style="background: #FEF0D9;"></div>
                <span>낮음</span>
            </div>
            <div class="legend-item">
                <div class="legend-color" style="background: #FDCC8A;"></div>
                <span>보통</span>
            </div>
            <div class="legend-item">
                <div class="legend-color" style="background: #FC8D59;"></div>
                <span>높음</span>
            </div>
            <div class="legend-item">
                <div class="legend-color" style="background: #D7301F;"></div>
                <span>매우 높음</span>
            </div>
        </div>
       
        <div class="info-panel">
            <h3>지역 정보</h3>
            <p>지도에서 지역을 클릭하면 상세 정보가 표시됩니다.</p>
            <div id="regionInfo" class="region-info"></div>
        </div>
    </div>

    <div class="tooltip" id="tooltip"></div>

    <script>
        // Data for visualization
        const populationData = {
            'KR-11': { value: 9720846, level: 'very-high', name: '서울특별시' },
            'KR-41': { value: 13239666, level: 'very-high', name: '경기도' },
            'KR-26': { value: 3404423, level: 'high', name: '부산광역시' },
            'KR-27': { value: 2438031, level: 'high', name: '대구광역시' },
            'KR-28': { value: 2963217, level: 'high', name: '인천광역시' },
            'KR-29': { value: 1456468, level: 'medium', name: '광주광역시' },
            'KR-30': { value: 1470972, level: 'medium', name: '대전광역시' },
            'KR-31': { value: 1135494, level: 'medium', name: '울산광역시' },
            'KR-42': { value: 1536270, level: 'medium', name: '강원도' },
            'KR-43': { value: 1597179, level: 'medium', name: '충청북도' },
            'KR-44': { value: 2118336, level: 'high', name: '충청남도' },
            'KR-45': { value: 1820092, level: 'medium', name: '전라북도' },
            'KR-46': { value: 1862567, level: 'medium', name: '전라남도' },
            'KR-47': { value: 2674474, level: 'high', name: '경상북도' },
            'KR-48': { value: 3373871, level: 'high', name: '경상남도' },
            'KR-49': { value: 677856, level: 'low', name: '제주특별자치도' }
        };
       
        const economicData = {
            'KR-11': { value: 100, level: 'very-high', name: '서울특별시' },
            'KR-41': { value: 85, level: 'high', name: '경기도' },
            'KR-26': { value: 70, level: 'medium', name: '부산광역시' },
            'KR-27': { value: 65, level: 'medium', name: '대구광역시' },
            'KR-28': { value: 75, level: 'high', name: '인천광역시' },
            'KR-29': { value: 60, level: 'medium', name: '광주광역시' },
            'KR-30': { value: 68, level: 'medium', name: '대전광역시' },
            'KR-31': { value: 80, level: 'high', name: '울산광역시' },
            'KR-42': { value: 55, level: 'low', name: '강원도' },
            'KR-43': { value: 58, level: 'low', name: '충청북도' },
            'KR-44': { value: 62, level: 'medium', name: '충청남도' },
            'KR-45': { value: 52, level: 'low', name: '전라북도' },
            'KR-46': { value: 50, level: 'low', name: '전라남도' },
            'KR-47': { value: 56, level: 'low', name: '경상북도' },
            'KR-48': { value: 64, level: 'medium', name: '경상남도' },
            'KR-49': { value: 72, level: 'medium', name: '제주특별자치도' }
        };
       
        let currentMode = 'default';
        let selectedRegion = null;
       
        // Initialize event listeners
        document.addEventListener('DOMContentLoaded', function() {
            const regions = document.querySelectorAll('.region');
            const tooltip = document.getElementById('tooltip');
           
            regions.forEach(region => {
                region.addEventListener('mouseenter', function(e) {
                    const name = this.getAttribute('data-name');
                    const code = this.getAttribute('data-code');
                   
                    let tooltipContent = `<strong>${name}</strong>`;
                   
                    if (currentMode === 'population' && populationData[code]) {
                        tooltipContent += `<br/>인구: ${populationData[code].value.toLocaleString()}명`;
                    } else if (currentMode === 'economic' && economicData[code]) {
                        tooltipContent += `<br/>경제지표: ${economicData[code].value} (서울=100 기준)`;
                    }
                   
                    tooltip.innerHTML = tooltipContent;
                    tooltip.style.opacity = '1';
                });
               
                region.addEventListener('mousemove', function(e) {
                    tooltip.style.left = (e.pageX + 10) + 'px';
                    tooltip.style.top = (e.pageY - 10) + 'px';
                });
               
                region.addEventListener('mouseleave', function() {
                    tooltip.style.opacity = '0';
                });
               
                region.addEventListener('click', function() {
                    const code = this.getAttribute('data-code');
                    showRegionInfo(code);
                   
                    // Update selection
                    if (selectedRegion) {
                        selectedRegion.classList.remove('selected');
                    }
                    selectedRegion = this;
                    this.classList.add('selected');
                });
            });
        });
       
        function showPopulation() {
            currentMode = 'population';
            const regions = document.querySelectorAll('.region');
           
            regions.forEach(region => {
                const code = region.getAttribute('data-code');
                const data = populationData[code];
               
                // Reset classes
                region.className = 'region';
               
                if (data) {
                    region.classList.add(`population-${data.level}`);
                }
            });
           
            updateLegend('population');
            hideRegionInfo();
        }
       
        function showEconomic() {
            currentMode = 'economic';
            const regions = document.querySelectorAll('.region');
           
            regions.forEach(region => {
                const code = region.getAttribute('data-code');
                const data = economicData[code];
               
                // Reset classes
                region.className = 'region';
               
                if (data) {
                    region.classList.add(`economic-${data.level}`);
                }
            });
           
            updateLegend('economic');
            hideRegionInfo();
        }
       
        function resetMap() {
            currentMode = 'default';
            const regions = document.querySelectorAll('.region');
           
            regions.forEach(region => {
                region.className = 'region';
            });
           
            if (selectedRegion) {
                selectedRegion.classList.remove('selected');
                selectedRegion = null;
            }
           
            updateLegend('default');
            hideRegionInfo();
           
            // Reset zoom
            const svg = document.getElementById('koreaMap');
            svg.setAttribute('viewBox', '0 0 800 600');
        }
       
        function zoomToSeoul() {
            const svg = document.getElementById('koreaMap');
            svg.setAttribute('viewBox', '300 120 200 150');
           
            const seoulRegion = document.getElementById('seoul');
            if (selectedRegion) {
                selectedRegion.classList.remove('selected');
            }
            selectedRegion = seoulRegion;
            seoulRegion.classList.add('selected');
           
            showRegionInfo('KR-11');
        }
       
        function updateLegend(mode) {
            const legend = document.getElementById('legend');
           
            if (mode === 'economic') {
                legend.innerHTML = `
                    <div class="legend-item">
                        <div class="legend-color" style="background: #F0F9E8;"></div>
                        <span>낮음 (50-60)</span>
                    </div>
                    <div class="legend-item">
                        <div class="legend-color" style="background: #BAE4BC;"></div>
                        <span>보통 (60-70)</span>
                    </div>
                    <div class="legend-item">
                        <div class="legend-color" style="background: #7BCCC4;"></div>
                        <span>높음 (70-85)</span>
                    </div>
                    <div class="legend-item">
                        <div class="legend-color" style="background: #2B8CBE;"></div>
                        <span>매우 높음 (85+)</span>
                    </div>
                `;
            } else {
                legend.innerHTML = `
                    <div class="legend-item">
                        <div class="legend-color" style="background: #FEF0D9;"></div>
                        <span>낮음</span>
                    </div>
                    <div class="legend-item">
                        <div class="legend-color" style="background: #FDCC8A;"></div>
                        <span>보통</span>
                    </div>
                    <div class="legend-item">
                        <div class="legend-color" style="background: #FC8D59;"></div>
                        <span>높음</span>
                    </div>
                    <div class="legend-item">
                        <div class="legend-color" style="background: #D7301F;"></div>
                        <span>매우 높음</span>
                    </div>
                `;
            }
        }
       
        function showRegionInfo(code) {
            const popData = populationData[code];
            const ecoData = economicData[code];
           
            if (!popData || !ecoData) return;
           
            const info = `
                <h4>${popData.name}</h4>
                <p><strong>인구:</strong> ${popData.value.toLocaleString()}명</p>
                <p><strong>경제지표:</strong> ${ecoData.value} (서울=100 기준)</p>
                <p><strong>지역코드:</strong> ${code}</p>
                <p><strong>인구 수준:</strong> ${getLevelText(popData.level)}</p>
                <p><strong>경제 수준:</strong> ${getLevelText(ecoData.level)}</p>
            `;
           
            document.getElementById('regionInfo').innerHTML = info;
            document.getElementById('regionInfo').style.display = 'block';
        }
       
        function hideRegionInfo() {
            document.getElementById('regionInfo').style.display = 'none';
        }
       
        function getLevelText(level) {
            const levels = {
                'low': '낮음',
                'medium': '보통',
                'high': '높음',
                'very-high': '매우 높음'
            };
            return levels[level] || level;
        }
       
        // Initialize with population data
        setTimeout(() => {
            showPopulation();
        }, 100);
    </script>
</body>
</html>