soiz1 commited on
Commit
bc22a6c
·
1 Parent(s): dc53e23

Update web-socket.html

Browse files
Files changed (1) hide show
  1. web-socket.html +59 -44
web-socket.html CHANGED
@@ -12,22 +12,34 @@
12
  src="https://unpkg.com/[email protected]/dist/leaflet.js"
13
  ></script>
14
  <style>
15
- table { border-collapse: collapse; width: 100%; margin-bottom: 20px;}
16
- th, td { border: 1px solid #ccc; padding: 8px; text-align: left; }
17
- th { background-color: #eee; }
18
- .highlight {
19
- background-color: #f99;
20
- transition: background-color 1s ease;
21
- }
22
  #map {
23
  height: 400px;
24
  width: 100%;
25
- margin-top: 20px;
26
  border: 1px solid #ccc;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  }
28
  </style>
29
  </head>
30
  <body>
 
 
31
  <h1>現在の接続ユーザー数: <span id="userCount">0</span></h1>
32
  <div>更新はページ再読み込みで行います。</div>
33
  <table>
@@ -42,57 +54,43 @@
42
  <tbody id="userTableBody"></tbody>
43
  </table>
44
 
45
- <div id="map"></div>
46
-
47
  <script>
48
  const socket = io("https://web-socket-server-14ap.onrender.com/");
49
 
50
  const STORAGE_KEY = "userSessions";
51
 
52
- // 前回セッション情報
53
  let previousSessions = JSON.parse(localStorage.getItem(STORAGE_KEY) || "{}");
54
 
55
  const userCountElem = document.getElementById("userCount");
56
  const tbody = document.getElementById("userTableBody");
57
- const mapDiv = document.getElementById("map");
58
 
59
- // Leafletマップ初期化
60
- const map = L.map('map').setView([35.681236, 139.767125], 5); // 東京を中心に
61
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
62
  maxZoom: 18,
63
  attribution: '© OpenStreetMap contributors'
64
  }).addTo(map);
65
 
66
- // マーカー管理用(socketId => marker)
67
  let markers = {};
68
 
69
- // IPアドレスから緯度経度を取得(ip-api.comを使用)
70
  async function fetchGeo(ip) {
71
- if(!ip || ip === "-") return null;
72
- try {
73
- const response = await fetch(`https://ip-api.com/json/${ip}?fields=status,message,lat,lon`);
74
- const data = await response.json();
75
- if(data.status === "success") {
76
- return { lat: data.lat, lon: data.lon };
77
- } else {
78
- console.warn(`IP位置情報取得失敗: ${ip} - ${data.message}`);
79
- return null;
80
- }
81
- } catch (e) {
82
- console.error("IP位置情報取得エラー", e);
83
- return null;
84
- }
85
  }
 
86
 
87
- // マーカーの色を指定するためのCircleMarkerを作る関数
88
  function createCircleMarker(lat, lon, color, popupText) {
89
  return L.circleMarker([lat, lon], {
90
- radius: 8,
91
  fillColor: color,
92
  color: '#000',
93
  weight: 1,
94
  opacity: 1,
95
- fillOpacity: 0.8
96
  }).bindPopup(popupText);
97
  }
98
 
@@ -101,15 +99,17 @@
101
  });
102
 
103
  socket.on("userSessionsUpdate", async (userSessions) => {
 
 
104
  tbody.innerHTML = "";
105
 
106
- // まず、すべてのマーカーを地図から削除
107
  for(let key in markers) {
108
  map.removeLayer(markers[key]);
109
  }
110
  markers = {};
111
 
112
- // すべてのIP位置取得を並列で実施
113
  const positions = {};
114
  await Promise.all(Object.entries(userSessions).map(async ([socketId, info]) => {
115
  positions[socketId] = await fetchGeo(info.ip);
@@ -142,17 +142,13 @@
142
 
143
  tbody.appendChild(tr);
144
 
145
- // 位置情報が取得できた場合、マーカー表示
146
  const pos = positions[socketId];
147
  if(pos) {
148
- // 前回位置と比較(緯度経度を比較)
149
  const prevPos = previousSessions[socketId]?.geoPosition;
150
  let changedPos = true;
151
  if(prevPos && Math.abs(prevPos.lat - pos.lat) < 0.0001 && Math.abs(prevPos.lon - pos.lon) < 0.0001) {
152
  changedPos = false;
153
  }
154
-
155
- // 色を決定:変化あれば赤丸、なければ黒丸
156
  const color = changedPos ? 'red' : 'black';
157
 
158
  const marker = createCircleMarker(pos.lat, pos.lon, color, `SocketID: ${socketId}<br>IP: ${info.ip || "-"}`);
@@ -161,7 +157,14 @@
161
  }
162
  }
163
 
164
- // 今回のデータにジオ位置も追加してlocalStorageに保存
 
 
 
 
 
 
 
165
  const sessionsToStore = {};
166
  for(const [socketId, info] of Object.entries(userSessions)) {
167
  sessionsToStore[socketId] = {
@@ -174,10 +177,22 @@
174
  previousSessions = sessionsToStore;
175
  });
176
 
177
- // 初回ロード時に前回のセッションを表示(あるなら)
178
- if (Object.keys(previousSessions).length > 0) {
179
- socket.emit("userSessionsUpdate", previousSessions);
180
- }
 
 
 
 
 
 
 
 
 
 
 
 
181
  </script>
182
  </body>
183
  </html>
 
12
  src="https://unpkg.com/[email protected]/dist/leaflet.js"
13
  ></script>
14
  <style>
 
 
 
 
 
 
 
15
  #map {
16
  height: 400px;
17
  width: 100%;
 
18
  border: 1px solid #ccc;
19
+ margin-bottom: 20px;
20
+ }
21
+ table {
22
+ border-collapse: collapse;
23
+ width: 100%;
24
+ margin-bottom: 20px;
25
+ }
26
+ th, td {
27
+ border: 1px solid #ccc;
28
+ padding: 8px;
29
+ text-align: left;
30
+ }
31
+ th {
32
+ background-color: #eee;
33
+ }
34
+ .highlight {
35
+ background-color: #f99;
36
+ transition: background-color 1s ease;
37
  }
38
  </style>
39
  </head>
40
  <body>
41
+ <div id="map"></div>
42
+
43
  <h1>現在の接続ユーザー数: <span id="userCount">0</span></h1>
44
  <div>更新はページ再読み込みで行います。</div>
45
  <table>
 
54
  <tbody id="userTableBody"></tbody>
55
  </table>
56
 
 
 
57
  <script>
58
  const socket = io("https://web-socket-server-14ap.onrender.com/");
59
 
60
  const STORAGE_KEY = "userSessions";
61
 
 
62
  let previousSessions = JSON.parse(localStorage.getItem(STORAGE_KEY) || "{}");
63
 
64
  const userCountElem = document.getElementById("userCount");
65
  const tbody = document.getElementById("userTableBody");
 
66
 
67
+ // Leafletマップ初期化(東京近辺)
68
+ const map = L.map('map').setView([35.681236, 139.767125], 5);
69
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
70
  maxZoom: 18,
71
  attribution: '© OpenStreetMap contributors'
72
  }).addTo(map);
73
 
 
74
  let markers = {};
75
 
76
+ // --- 簡易テスト用IP座標返し関数 ---
77
  async function fetchGeo(ip) {
78
+ const knownIPs = {
79
+ "8.8.8.8": {lat: 37.386, lon: -122.0838}, // Google DNS
80
+ "1.1.1.1": {lat: -33.4940, lon: 143.2104} // Cloudflare DNS
81
+ };
82
+ return knownIPs[ip] || null;
 
 
 
 
 
 
 
 
 
83
  }
84
+ // ----------------------------------
85
 
 
86
  function createCircleMarker(lat, lon, color, popupText) {
87
  return L.circleMarker([lat, lon], {
88
+ radius: 10,
89
  fillColor: color,
90
  color: '#000',
91
  weight: 1,
92
  opacity: 1,
93
+ fillOpacity: 0.9
94
  }).bindPopup(popupText);
95
  }
96
 
 
99
  });
100
 
101
  socket.on("userSessionsUpdate", async (userSessions) => {
102
+ console.log("userSessionsUpdate受信", userSessions);
103
+
104
  tbody.innerHTML = "";
105
 
106
+ // 既存マーカーを削除
107
  for(let key in markers) {
108
  map.removeLayer(markers[key]);
109
  }
110
  markers = {};
111
 
112
+ // IPごとの位置情報を取得
113
  const positions = {};
114
  await Promise.all(Object.entries(userSessions).map(async ([socketId, info]) => {
115
  positions[socketId] = await fetchGeo(info.ip);
 
142
 
143
  tbody.appendChild(tr);
144
 
 
145
  const pos = positions[socketId];
146
  if(pos) {
 
147
  const prevPos = previousSessions[socketId]?.geoPosition;
148
  let changedPos = true;
149
  if(prevPos && Math.abs(prevPos.lat - pos.lat) < 0.0001 && Math.abs(prevPos.lon - pos.lon) < 0.0001) {
150
  changedPos = false;
151
  }
 
 
152
  const color = changedPos ? 'red' : 'black';
153
 
154
  const marker = createCircleMarker(pos.lat, pos.lon, color, `SocketID: ${socketId}<br>IP: ${info.ip || "-"}`);
 
157
  }
158
  }
159
 
160
+ // マーカー全体を囲んで地図を移動
161
+ const markerPositions = Object.values(markers).map(m => m.getLatLng());
162
+ if(markerPositions.length > 0) {
163
+ const group = L.featureGroup(Object.values(markers));
164
+ map.fitBounds(group.getBounds().pad(0.5));
165
+ }
166
+
167
+ // localStorageに保存
168
  const sessionsToStore = {};
169
  for(const [socketId, info] of Object.entries(userSessions)) {
170
  sessionsToStore[socketId] = {
 
177
  previousSessions = sessionsToStore;
178
  });
179
 
180
+ // テスト用に手動発火
181
+ window.addEventListener("load", () => {
182
+ const testData = {
183
+ "test-socket-1": {
184
+ ip: "8.8.8.8",
185
+ connectTime: Date.now(),
186
+ disconnectTime: null
187
+ },
188
+ "test-socket-2": {
189
+ ip: "1.1.1.1",
190
+ connectTime: Date.now(),
191
+ disconnectTime: null
192
+ }
193
+ };
194
+ socket.emit("userSessionsUpdate", testData);
195
+ });
196
  </script>
197
  </body>
198
  </html>