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> |