tuhbooh commited on
Commit
735aaeb
·
verified ·
1 Parent(s): d4b1b68

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +121 -121
index.html CHANGED
@@ -3,137 +3,137 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Leaflet Mega GUI - Minh Đức</title>
7
-
8
- <!-- Core Leaflet CSS -->
9
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
10
-
11
- <!-- Plugin CSS Libraries -->
12
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet.fullscreen@2.4.0/Control.FullScreen.css" />
13
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet.locatecontrol@0.79.0/dist/L.Control.Locate.min.css" />
14
- <link rel="stylesheet" href="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.css" />
15
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.css" />
16
- <link rel="stylesheet" href="https://unpkg.com/leaflet-minimap@3.6.1/dist/Control.MiniMap.min.css" />
17
- <link rel="stylesheet" href="https://ppete2.github.io/Leaflet.PolylineMeasure/Leaflet.PolylineMeasure.css" />
18
-
19
  <style>
20
- body, html { margin: 0; padding: 0; height: 100%; width: 100%; overflow: hidden; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
21
  #map { height: 100%; width: 100%; }
22
-
23
- /* Làm đẹp các thanh điều khiển */
24
- .leaflet-control { border: none !important; box-shadow: 0 2px 6px rgba(0,0,0,0.3) !important; }
25
  .map-title {
26
- position: absolute;
27
- top: 10px;
28
- left: 50%;
29
- transform: translateX(-50%);
30
- z-index: 1000;
31
- background: rgba(255, 255, 255, 0.9);
32
- padding: 5px 20px;
33
- border-radius: 20px;
34
- font-weight: bold;
35
- box-shadow: 0 2px 5px rgba(0,0,0,0.2);
36
- pointer-events: none;
37
  }
38
  </style>
39
  </head>
40
  <body>
41
 
42
- <div class="map-title">Leaflet Ultimate GUI</div>
43
- <div id="map"></div>
44
-
45
- <!-- Core Leaflet JS -->
46
- <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
47
-
48
- <!-- Plugin JS Libraries -->
49
- <script src="https://cdn.jsdelivr.net/npm/leaflet.fullscreen@2.4.0/Control.FullScreen.min.js"></script>
50
- <script src="https://cdn.jsdelivr.net/npm/leaflet.locatecontrol@0.79.0/dist/L.Control.Locate.min.js"></script>
51
- <script src="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.js"></script>
52
- <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js"></script>
53
- <script src="https://unpkg.com/leaflet-minimap@3.6.1/dist/Control.MiniMap.min.js"></script>
54
- <script src="https://ppete2.github.io/Leaflet.PolylineMeasure/Leaflet.PolylineMeasure.js"></script>
55
-
56
- <script>
57
- window.onload = function() {
58
- // 1. Cấu hình các lớp nền (Base Layers)
59
- const osm = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
60
- attribution: '© OpenStreetMap'
61
- });
62
-
63
- const satellite = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
64
- attribution: Esri'
65
- });
66
-
67
- const terrain = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
68
- attribution: OpenTopoMap'
69
- });
70
-
71
- // 2. Khởi tạo bản đồ
72
- const map = L.map('map', {
73
- center: [10.7626, 106.6602],
74
- zoom: 13,
75
- layers: [osm],
76
- fullscreenControl: true
77
- });
78
-
79
- // 3. GUI: Lớp điều khiển bản đồ (Layer Control)
80
- const baseMaps = {
81
- "Bản đồ đường đi": osm,
82
- "Vệ tinh": satellite,
83
- "Địa hình": terrain
84
- };
85
- L.control.layers(baseMaps).addTo(map);
86
-
87
- // 4. GUI: Định vị (Locate)
88
- L.control.locate({
89
- strings: { title: "Vị trí của tôi" },
90
- locateOptions: { maxZoom: 16 }
91
- }).addTo(map);
92
-
93
- // 5. GUI: Tìm kiếm (Search/Geocoder)
94
- L.Control.geocoder({
95
- defaultMarkGeocode: true,
96
- placeholder: "Tìm địa chỉ..."
97
- }).addTo(map);
98
-
99
- // 6. GUI: Thước đo (Polyline Measure) - Nút hình cây thước
100
- L.control.polylineMeasure({
101
- position: 'topleft',
102
- unit: 'metres',
103
- showBearings: true,
104
- clearMeasurementsOnStop: false,
105
- showUnitControl: true
106
- }).addTo(map);
107
-
108
- // 7. GUI: Công cụ vẽ (Drawing Tools) - Hình vuông, tròn, đa giác
109
- const drawnItems = new L.FeatureGroup();
110
- map.addLayer(drawnItems);
111
- const drawControl = new L.Control.Draw({
112
- edit: { featureGroup: drawnItems },
113
- draw: { polygon: true, polyline: true, rectangle: true, circle: true, marker: true }
114
- });
115
- map.addControl(drawControl);
116
-
117
- map.on(L.Draw.Event.CREATED, function (event) {
118
- drawnItems.addLayer(event.layer);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  });
 
 
120
 
121
- // 8. GUI: Bản đồ thu nhỏ (MiniMap) - Góc dưới bên phải
122
- const osm2 = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png');
123
- new L.Control.MiniMap(osm2, { toggleDisplay: true, minimized: false }).addTo(map);
124
-
125
- // 9. GUI: Thước tỉ lệ (Scale)
126
- L.control.scale({ imperial: false }).addTo(map);
127
-
128
- // Hiện tọa độ khi click
129
- map.on('click', function(e) {
130
- L.popup()
131
- .setLatLng(e.latlng)
132
- .setContent("Tọa độ: " + e.latlng.lat.toFixed(6) + ", " + e.latlng.lng.toFixed(6))
133
- .openOn(map);
134
- });
135
- };
136
- </script>
137
  </body>
138
  </html>
139
-
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Leaflet Realtime P2P - Minh Đức</title>
 
 
7
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
 
 
 
 
 
 
 
 
 
8
  <style>
9
+ body, html { margin: 0; padding: 0; height: 100%; overflow: hidden; font-family: sans-serif; }
10
  #map { height: 100%; width: 100%; }
 
 
 
11
  .map-title {
12
+ position: absolute; top: 10px; left: 50%; transform: translateX(-50%);
13
+ z-index: 1000; background: white; padding: 8px 15px;
14
+ border-radius: 20px; font-weight: bold; box-shadow: 0 2px 5px rgba(0,0,0,0.2);
15
+ }
16
+ .status-bar {
17
+ position: absolute; bottom: 20px; left: 10px; z-index: 1000;
18
+ background: rgba(0,0,0,0.7); color: white; padding: 5px 10px;
19
+ font-size: 12px; border-radius: 5px;
 
 
 
20
  }
21
  </style>
22
  </head>
23
  <body>
24
 
25
+ <div class="map-title">📍 Bản đồ Realtime P2P - Minh Đức</div>
26
+ <div id="map"></div>
27
+ <div class="status-bar" id="status">Đang khởi tạo Peer...</div>
28
+
29
+ <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
30
+ <script src="https://unpkg.com/peerjs@1.5.2/dist/peerjs.min.js"></script>
31
+
32
+ <script>
33
+ // --- CẤU HÌNH ---
34
+ const ROOM_PREFIX = "minh-duc-room-";
35
+ const MAX_PEERS = 10; // Quét tối đa 10 người để tránh lag
36
+ const remoteMarkers = {};
37
+
38
+ // --- KHỞI TẠO BẢN ĐỒ ---
39
+ const map = L.map('map').setView([10.7626, 106.6602], 13);
40
+ L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
41
+ attribution: OpenStreetMap'
42
+ }).addTo(map);
43
+
44
+ // Marker riêng cho bạn bè (Màu đỏ)
45
+ const friendIcon = L.icon({
46
+ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-red.png',
47
+ iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34]
48
+ });
49
+
50
+ // --- LOGIC PEERJS ---
51
+ const myNumber = Math.floor(Math.random() * MAX_PEERS);
52
+ const myId = ROOM_PREFIX + myNumber;
53
+ const peer = new Peer(myId);
54
+
55
+ document.getElementById('status').innerText = "ID của bạn: " + myId + " (Đang quét bạn bè...)";
56
+
57
+ peer.on('open', (id) => {
58
+ // Tự động tìm kết nối với các ID khác trong dải từ 0 - MAX_PEERS
59
+ for (let i = 0; i < MAX_PEERS; i++) {
60
+ if (i !== myNumber) {
61
+ connectToPeer(ROOM_PREFIX + i);
62
+ }
63
+ }
64
+ });
65
+
66
+ peer.on('connection', (conn) => {
67
+ handleData(conn);
68
+ });
69
+
70
+ function connectToPeer(targetId) {
71
+ const conn = peer.connect(targetId);
72
+ handleData(conn);
73
+ }
74
+
75
+ function handleData(conn) {
76
+ conn.on('data', async (data) => {
77
+ if (data.lat && data.lng) {
78
+ // Nếu chưa có marker hoặc người dùng di chuyển xa, cập nhật địa chỉ
79
+ updateUserOnMap(conn.peer, data);
80
+ }
81
+ });
82
+ }
83
+
84
+ // --- HÀM LẤY ĐỊA CHỈ TỪ TỌA ĐỘ (Reverse Geocoding) ---
85
+ // Sử dụng Nominatim miễn phí, không cần API Key
86
+ async function getAddress(lat, lng) {
87
+ try {
88
+ const response = await fetch(`https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lng}&zoom=18&addressdetails=1`);
89
+ const data = await response.json();
90
+ return data.display_name || "Không xác định được địa chỉ";
91
+ } catch (error) {
92
+ return "Lỗi lấy địa chỉ";
93
+ }
94
+ }
95
+
96
+ async function updateUserOnMap(peerId, coords) {
97
+ if (remoteMarkers[peerId]) {
98
+ // Cập nhật vị trí marker
99
+ remoteMarkers[peerId].marker.setLatLng([coords.lat, coords.lng]);
100
+
101
+ // Cứ sau mỗi 10 giây hoặc khi click mới cập nhật lại địa chỉ để tránh spam server Nominatim
102
+ if (Date.now() - remoteMarkers[peerId].lastUpdate > 10000) {
103
+ const addr = await getAddress(coords.lat, coords.lng);
104
+ remoteMarkers[peerId].marker.getPopup().setContent(`<b>User: ${peerId}</b><br>${addr}`);
105
+ remoteMarkers[peerId].lastUpdate = Date.now();
106
+ }
107
+ } else {
108
+ // Tạo mới marker
109
+ const addr = await getAddress(coords.lat, coords.lng);
110
+ const marker = L.marker([coords.lat, coords.lng], {icon: friendIcon})
111
+ .addTo(map)
112
+ .bindPopup(`<b>User: ${peerId}</b><br>${addr}`);
113
+
114
+ remoteMarkers[peerId] = { marker, lastUpdate: Date.now() };
115
+ }
116
+ }
117
+
118
+ // --- GỬI VỊ TRÍ MỖI 1 GIÂY ---
119
+ setInterval(() => {
120
+ if (navigator.geolocation) {
121
+ navigator.geolocation.getCurrentPosition((position) => {
122
+ const myData = {
123
+ lat: position.coords.latitude,
124
+ lng: position.coords.longitude
125
+ };
126
+
127
+ // Gửi dữ liệu cho tất cả các kết nối đang mở
128
+ Object.values(peer.connections).forEach(conns => {
129
+ conns.forEach(c => {
130
+ if (c.open) c.send(myData);
131
+ });
132
+ });
133
  });
134
+ }
135
+ }, 1000);
136
 
137
+ </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  </body>
139
  </html>