Update index.html
Browse files- index.html +73 -10
index.html
CHANGED
|
@@ -325,6 +325,9 @@
|
|
| 325 |
const scales = [2500, 5000, 10000, 25000, 50000];
|
| 326 |
let currentScaleIndex = 1; // 기본 1:5000
|
| 327 |
let currentScale = scales[currentScaleIndex];
|
|
|
|
|
|
|
|
|
|
| 328 |
|
| 329 |
// 지형 데이터를 저장할 변수들
|
| 330 |
let heightMap = [];
|
|
@@ -337,6 +340,9 @@
|
|
| 337 |
let showRivers = true;
|
| 338 |
let terrainType = 'mountain';
|
| 339 |
let seed = Math.random() * 10000;
|
|
|
|
|
|
|
|
|
|
| 340 |
|
| 341 |
// 개선된 노이즈 함수
|
| 342 |
function noise(x, y, scale, octaves, seed) {
|
|
@@ -595,6 +601,12 @@
|
|
| 595 |
function drawMap() {
|
| 596 |
ctx.clearRect(0, 0, WIDTH, HEIGHT);
|
| 597 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 598 |
const gridSize = heightMap.length;
|
| 599 |
const cellWidth = WIDTH / gridSize;
|
| 600 |
const cellHeight = HEIGHT / gridSize;
|
|
@@ -742,6 +754,7 @@
|
|
| 742 |
});
|
| 743 |
|
| 744 |
// 축척 막대 그리기
|
|
|
|
| 745 |
drawScaleBar();
|
| 746 |
}
|
| 747 |
|
|
@@ -840,8 +853,19 @@
|
|
| 840 |
// 마우스 이벤트
|
| 841 |
canvas.addEventListener('mousemove', (e) => {
|
| 842 |
const rect = canvas.getBoundingClientRect();
|
| 843 |
-
|
| 844 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 845 |
|
| 846 |
const gridSize = heightMap.length;
|
| 847 |
const gridX = Math.floor(x / (WIDTH / gridSize));
|
|
@@ -859,9 +883,11 @@
|
|
| 859 |
slope = Math.round(Math.sqrt(dx * dx + dy * dy) * 100);
|
| 860 |
}
|
| 861 |
|
| 862 |
-
// 실제 거리 계산
|
| 863 |
-
const
|
| 864 |
-
const
|
|
|
|
|
|
|
| 865 |
|
| 866 |
document.getElementById('coordinates').textContent = `${gridX}, ${gridY}`;
|
| 867 |
document.getElementById('elevation').textContent = `${elevation}m`;
|
|
@@ -875,7 +901,24 @@
|
|
| 875 |
}
|
| 876 |
});
|
| 877 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 878 |
canvas.addEventListener('mouseleave', () => {
|
|
|
|
|
|
|
| 879 |
tooltip.style.display = 'none';
|
| 880 |
document.getElementById('coordinates').textContent = '-';
|
| 881 |
document.getElementById('elevation').textContent = '-';
|
|
@@ -883,6 +926,19 @@
|
|
| 883 |
document.getElementById('realDistance').textContent = '-';
|
| 884 |
});
|
| 885 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 886 |
// 컨트롤 함수들
|
| 887 |
function generateNewTerrain() {
|
| 888 |
generateTerrain();
|
|
@@ -919,6 +975,9 @@
|
|
| 919 |
if (currentScaleIndex > 0) {
|
| 920 |
currentScaleIndex--;
|
| 921 |
currentScale = scales[currentScaleIndex];
|
|
|
|
|
|
|
|
|
|
| 922 |
updateScaleInfo();
|
| 923 |
drawMap();
|
| 924 |
}
|
|
@@ -928,24 +987,28 @@
|
|
| 928 |
if (currentScaleIndex < scales.length - 1) {
|
| 929 |
currentScaleIndex++;
|
| 930 |
currentScale = scales[currentScaleIndex];
|
|
|
|
|
|
|
|
|
|
| 931 |
updateScaleInfo();
|
| 932 |
drawMap();
|
| 933 |
}
|
| 934 |
}
|
| 935 |
|
| 936 |
function updateScaleInfo() {
|
| 937 |
-
|
|
|
|
| 938 |
|
| 939 |
-
// 지도 전체 크기 계산
|
| 940 |
-
const widthKm = (WIDTH *
|
| 941 |
-
const heightKm = (HEIGHT *
|
| 942 |
|
| 943 |
// 최대 20km x 15km 제한
|
| 944 |
const actualWidthKm = Math.min(20, widthKm);
|
| 945 |
const actualHeightKm = Math.min(15, heightKm);
|
| 946 |
|
| 947 |
document.getElementById('mapSizeInfo').textContent =
|
| 948 |
-
`지도 범위: ${actualWidthKm}km × ${actualHeightKm}km`;
|
| 949 |
}
|
| 950 |
|
| 951 |
function exportMap() {
|
|
|
|
| 325 |
const scales = [2500, 5000, 10000, 25000, 50000];
|
| 326 |
let currentScaleIndex = 1; // 기본 1:5000
|
| 327 |
let currentScale = scales[currentScaleIndex];
|
| 328 |
+
let zoomLevel = 1; // 줌 레벨 (0.5 ~ 4)
|
| 329 |
+
let offsetX = 0; // 뷰포트 오프셋
|
| 330 |
+
let offsetY = 0;
|
| 331 |
|
| 332 |
// 지형 데이터를 저장할 변수들
|
| 333 |
let heightMap = [];
|
|
|
|
| 340 |
let showRivers = true;
|
| 341 |
let terrainType = 'mountain';
|
| 342 |
let seed = Math.random() * 10000;
|
| 343 |
+
let isDragging = false;
|
| 344 |
+
let dragStartX = 0;
|
| 345 |
+
let dragStartY = 0;
|
| 346 |
|
| 347 |
// 개선된 노이즈 함수
|
| 348 |
function noise(x, y, scale, octaves, seed) {
|
|
|
|
| 601 |
function drawMap() {
|
| 602 |
ctx.clearRect(0, 0, WIDTH, HEIGHT);
|
| 603 |
|
| 604 |
+
// 줌과 오프셋 적용
|
| 605 |
+
ctx.save();
|
| 606 |
+
ctx.translate(WIDTH/2, HEIGHT/2);
|
| 607 |
+
ctx.scale(zoomLevel, zoomLevel);
|
| 608 |
+
ctx.translate(-WIDTH/2 + offsetX, -HEIGHT/2 + offsetY);
|
| 609 |
+
|
| 610 |
const gridSize = heightMap.length;
|
| 611 |
const cellWidth = WIDTH / gridSize;
|
| 612 |
const cellHeight = HEIGHT / gridSize;
|
|
|
|
| 754 |
});
|
| 755 |
|
| 756 |
// 축척 막대 그리기
|
| 757 |
+
ctx.restore(); // 줌 효과 제거 후 축척 막대 그리기
|
| 758 |
drawScaleBar();
|
| 759 |
}
|
| 760 |
|
|
|
|
| 853 |
// 마우스 이벤트
|
| 854 |
canvas.addEventListener('mousemove', (e) => {
|
| 855 |
const rect = canvas.getBoundingClientRect();
|
| 856 |
+
|
| 857 |
+
if (isDragging) {
|
| 858 |
+
const dx = e.clientX - dragStartX;
|
| 859 |
+
const dy = e.clientY - dragStartY;
|
| 860 |
+
offsetX = dx / zoomLevel;
|
| 861 |
+
offsetY = dy / zoomLevel;
|
| 862 |
+
drawMap();
|
| 863 |
+
return;
|
| 864 |
+
}
|
| 865 |
+
|
| 866 |
+
// 줌을 고려한 마우스 좌표 계산
|
| 867 |
+
const x = ((e.clientX - rect.left) * (WIDTH / rect.width) - WIDTH/2) / zoomLevel + WIDTH/2 - offsetX;
|
| 868 |
+
const y = ((e.clientY - rect.top) * (HEIGHT / rect.height) - HEIGHT/2) / zoomLevel + HEIGHT/2 - offsetY;
|
| 869 |
|
| 870 |
const gridSize = heightMap.length;
|
| 871 |
const gridX = Math.floor(x / (WIDTH / gridSize));
|
|
|
|
| 883 |
slope = Math.round(Math.sqrt(dx * dx + dy * dy) * 100);
|
| 884 |
}
|
| 885 |
|
| 886 |
+
// 실제 거리 계산 (줌 레벨 고려)
|
| 887 |
+
const mapWidthKm = (WIDTH * currentScale / zoomLevel) / 1000000;
|
| 888 |
+
const mapHeightKm = (HEIGHT * currentScale / zoomLevel) / 1000000;
|
| 889 |
+
const realX = (gridX * mapWidthKm / gridSize).toFixed(2);
|
| 890 |
+
const realY = (gridY * mapHeightKm / gridSize).toFixed(2);
|
| 891 |
|
| 892 |
document.getElementById('coordinates').textContent = `${gridX}, ${gridY}`;
|
| 893 |
document.getElementById('elevation').textContent = `${elevation}m`;
|
|
|
|
| 901 |
}
|
| 902 |
});
|
| 903 |
|
| 904 |
+
// 드래그 이벤트
|
| 905 |
+
canvas.addEventListener('mousedown', (e) => {
|
| 906 |
+
if (e.button === 0) { // 왼쪽 버튼
|
| 907 |
+
isDragging = true;
|
| 908 |
+
dragStartX = e.clientX - offsetX * zoomLevel;
|
| 909 |
+
dragStartY = e.clientY - offsetY * zoomLevel;
|
| 910 |
+
canvas.style.cursor = 'grabbing';
|
| 911 |
+
}
|
| 912 |
+
});
|
| 913 |
+
|
| 914 |
+
canvas.addEventListener('mouseup', () => {
|
| 915 |
+
isDragging = false;
|
| 916 |
+
canvas.style.cursor = 'crosshair';
|
| 917 |
+
});
|
| 918 |
+
|
| 919 |
canvas.addEventListener('mouseleave', () => {
|
| 920 |
+
isDragging = false;
|
| 921 |
+
canvas.style.cursor = 'crosshair';
|
| 922 |
tooltip.style.display = 'none';
|
| 923 |
document.getElementById('coordinates').textContent = '-';
|
| 924 |
document.getElementById('elevation').textContent = '-';
|
|
|
|
| 926 |
document.getElementById('realDistance').textContent = '-';
|
| 927 |
});
|
| 928 |
|
| 929 |
+
// 마우스 휠 줌
|
| 930 |
+
canvas.addEventListener('wheel', (e) => {
|
| 931 |
+
e.preventDefault();
|
| 932 |
+
const delta = e.deltaY > 0 ? 0.9 : 1.1;
|
| 933 |
+
const newZoom = zoomLevel * delta;
|
| 934 |
+
|
| 935 |
+
if (newZoom >= 0.5 && newZoom <= 4) {
|
| 936 |
+
zoomLevel = newZoom;
|
| 937 |
+
updateScaleInfo();
|
| 938 |
+
drawMap();
|
| 939 |
+
}
|
| 940 |
+
});
|
| 941 |
+
|
| 942 |
// 컨트롤 함수들
|
| 943 |
function generateNewTerrain() {
|
| 944 |
generateTerrain();
|
|
|
|
| 975 |
if (currentScaleIndex > 0) {
|
| 976 |
currentScaleIndex--;
|
| 977 |
currentScale = scales[currentScaleIndex];
|
| 978 |
+
zoomLevel = Math.min(4, zoomLevel * 1.5);
|
| 979 |
+
offsetX = 0;
|
| 980 |
+
offsetY = 0;
|
| 981 |
updateScaleInfo();
|
| 982 |
drawMap();
|
| 983 |
}
|
|
|
|
| 987 |
if (currentScaleIndex < scales.length - 1) {
|
| 988 |
currentScaleIndex++;
|
| 989 |
currentScale = scales[currentScaleIndex];
|
| 990 |
+
zoomLevel = Math.max(0.5, zoomLevel / 1.5);
|
| 991 |
+
offsetX = 0;
|
| 992 |
+
offsetY = 0;
|
| 993 |
updateScaleInfo();
|
| 994 |
drawMap();
|
| 995 |
}
|
| 996 |
}
|
| 997 |
|
| 998 |
function updateScaleInfo() {
|
| 999 |
+
const effectiveScale = currentScale / zoomLevel;
|
| 1000 |
+
document.getElementById('scaleInfo').textContent = `1:${Math.round(effectiveScale)}`;
|
| 1001 |
|
| 1002 |
+
// 지도 전체 크기 계산 (줌 고려)
|
| 1003 |
+
const widthKm = (WIDTH * effectiveScale / 1000000).toFixed(1);
|
| 1004 |
+
const heightKm = (HEIGHT * effectiveScale / 1000000).toFixed(1);
|
| 1005 |
|
| 1006 |
// 최대 20km x 15km 제한
|
| 1007 |
const actualWidthKm = Math.min(20, widthKm);
|
| 1008 |
const actualHeightKm = Math.min(15, heightKm);
|
| 1009 |
|
| 1010 |
document.getElementById('mapSizeInfo').textContent =
|
| 1011 |
+
`지도 범위: ${actualWidthKm}km × ${actualHeightKm}km (줌: ${(zoomLevel * 100).toFixed(0)}%)`;
|
| 1012 |
}
|
| 1013 |
|
| 1014 |
function exportMap() {
|