-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
312 lines (282 loc) · 16.8 KB
/
index.html
File metadata and controls
312 lines (282 loc) · 16.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WhereShot - 撮影時刻・場所解析ツール</title>
<meta name="description" content="画像・動画から撮影時刻・場所を解析するOSINT支援ツール">
<meta name="author" content="IPUSIRON">
<!-- セキュリティヘッダー -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-inline' 'unsafe-eval' https: data: blob:">
<!-- Leaflet CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.css" integrity="sha512-Zcn6bjR/8RZbLEpLIeOwNtzREBAJnUKESxces60Mpoj+2okopSAcSUIUOseddDm0cxnGQzxIR7vJgsLZbdLE3w==" crossorigin="anonymous">
<!-- アプリケーションCSS -->
<link rel="stylesheet" href="css/style.css">
<!-- Favicon -->
<link rel="icon" type="image/x-icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>📸</text></svg>">
</head>
<body>
<div class="app-container">
<!-- ヘッダー -->
<header class="app-header">
<div class="header-content">
<h1 class="app-title">
<span class="title-main">WhereShot</span>
<span class="title-sub">撮影時刻・場所解析ツール</span>
</h1>
<div class="header-actions">
<button id="help-btn" class="btn btn-secondary">ヘルプ</button>
<button id="clear-btn" class="btn btn-danger">リセット</button>
</div>
</div>
</header>
<!-- メインコンテンツ -->
<main class="main-content">
<!-- ファイルアップロード エリア -->
<section class="upload-section">
<div id="drop-zone" class="drop-zone">
<div class="drop-zone-content">
<div class="upload-icon">📸</div>
<h3>画像をドラッグ&ドロップ</h3>
<p>または <button id="file-select-btn" class="btn btn-primary">ファイルを選択</button></p>
<small>対応形式: JPEG, PNG, TIFF, MP4</small>
</div>
<input type="file" id="file-input" accept="image/*,video/mp4" style="display: none;">
</div>
<!-- 画像プレビューエリア -->
<div id="image-preview" class="image-preview" style="display: none;">
<div class="preview-header">
<h3>📁 アップロードファイル</h3>
<div class="preview-controls">
<button id="toggle-preview-btn" class="btn btn-secondary">🔍 プレビュー表示</button>
<button id="change-file-btn" class="btn btn-secondary">📂 別ファイル選択</button>
</div>
</div>
<div class="preview-content">
<div class="file-info">
<div class="file-basic-info">
<p><strong>📄 ファイル名:</strong> <span id="file-name">-</span></p>
<p><strong>📊 ファイルサイズ:</strong> <span id="file-size">-</span></p>
<p><strong>🎭 形式:</strong> <span id="file-type">-</span></p>
<p><strong>📅 更新日:</strong> <span id="file-modified">-</span></p>
</div>
</div>
<div id="image-display" class="image-display" style="display: none;">
<img id="preview-img" src="" alt="プレビュー画像" />
<div class="privacy-notice">
<small>🔒 プライバシー保護: 画像はローカルでのみ表示され、外部に送信されません</small>
</div>
</div>
</div>
</div>
</section>
<!-- 解析結果表示エリア -->
<div id="analysis-results" class="analysis-results" style="display: none;">
<!-- Exif情報パネル -->
<section class="info-panel">
<h2>📊 Exif メタデータ</h2>
<div class="info-grid">
<div class="info-card">
<h4>📅 撮影日時</h4>
<div id="datetime-info" class="info-content">-</div>
</div>
<div class="info-card">
<h4>📍 GPS位置</h4>
<div id="gps-info" class="info-content">-</div>
</div>
<div class="info-card">
<h4>📷 カメラ情報</h4>
<div id="camera-info" class="info-content">-</div>
</div>
<div class="info-card">
<h4>⚙️ 撮影設定</h4>
<div id="settings-info" class="info-content">-</div>
</div>
</div>
<!-- 推定日時セクション -->
<div class="datetime-estimation-section">
<h3>🔍 日時推定</h3>
<div class="estimation-result">
<div class="estimated-datetime">
<div class="estimation-header">
<h4>推定日時</h4>
<button id="set-estimated-datetime-btn" class="btn btn-primary" style="display: none;">
📅 解析日時にセット
</button>
</div>
<div id="estimated-datetime-value" class="estimation-value">-</div>
<div id="estimation-confidence" class="estimation-confidence">-</div>
</div>
<div id="estimation-warnings" class="estimation-warnings" style="display: none;">
<!-- 警告メッセージがここに表示される -->
</div>
<div class="estimation-sources">
<h5>日時ソース</h5>
<div id="datetime-sources" class="sources-list">
<div class="source-item">
<span class="source-type">解析待機中...</span>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- 地図パネル(修正版) -->
<section class="map-panel">
<h2>🗺️ 撮影地点マップ</h2>
<div class="map-controls">
<button id="manual-location-btn" class="btn btn-secondary">手動で位置指定</button>
<button id="direction-mode-btn" class="btn btn-secondary">撮影方向を設定</button>
<select id="map-layer-select" class="form-select">
<option value="osm">OpenStreetMap</option>
<option value="satellite">衛星画像</option>
<option value="terrain">地形図</option>
</select>
</div>
<!-- 地図コンテナ - 修正版 -->
<div class="map-wrapper">
<div id="map" class="map-container map-initializing"
style="width: 100%; height: 500px; min-height: 400px; background: var(--bg-card); position: relative;">
</div>
<div class="map-info">
<small id="map-coordinates">地図を読み込み中...</small>
</div>
</div>
</section>
<!-- 太陽位置計算パネル -->
<section class="sun-panel">
<h2>🌞 太陽位置・影解析</h2>
<div class="sun-controls">
<label for="analysis-date">解析日時:</label>
<input type="datetime-local" id="analysis-date" class="form-input">
<button id="calculate-sun-btn" class="btn btn-primary">計算実行</button>
</div>
<div id="sun-results" class="sun-results">
<div class="sun-info-grid">
<div class="sun-info-card">
<h4>☀️ 太陽高度</h4>
<div id="sun-elevation" class="sun-value">-</div>
</div>
<div class="sun-info-card">
<h4>🧭 太陽方位</h4>
<div id="sun-azimuth" class="sun-value">-</div>
</div>
<div class="sun-info-card">
<h4>🌅 時間帯</h4>
<div id="sun-phase" class="sun-value">-</div>
</div>
<div class="sun-info-card">
<h4>🔗 詳細確認</h4>
<a id="suncalc-link" href="#" target="_blank" class="btn btn-link">SunCalc.org</a>
</div>
</div>
</div>
</section>
<!-- 外部データ連携パネル -->
<section class="external-panel">
<h2>🌐 外部データ連携</h2>
<div class="external-links">
<div class="link-group">
<h4>🛰️ 衛星画像・気象データ</h4>
<a id="nasa-worldview-link" href="#" target="_blank" rel="noopener noreferrer" class="btn btn-external">NASA Worldview</a>
<a id="weather-link" href="#" target="_blank" rel="noopener noreferrer" class="btn btn-external">過去の天気</a>
</div>
<div class="link-group">
<h4>🗾 地理院地図・空中写真</h4>
<a id="gsi-map-link" href="#" target="_blank" rel="noopener noreferrer" class="btn btn-external">地理院地図</a>
<a id="gsi-photo-link" href="#" target="_blank" rel="noopener noreferrer" class="btn btn-external">空中写真</a>
</div>
<div class="link-group">
<h4>🔍 その他の検証ツール</h4>
<a id="streetview-link" href="#" target="_blank" rel="noopener noreferrer" class="btn btn-external">Street View</a>
<a id="reverse-image-link" href="https://images.google.com/" target="_blank" rel="noopener noreferrer" class="btn btn-external">Google画像検索を開く</a>
<small>※ プレビュー画像を右クリック → 「Googleで画像を検索」 で利用できます</small>
</div>
</div>
</section>
</div>
</main>
<!-- フッター区切り線 -->
<hr class="footer-divider">
<!-- フッター -->
<footer class="app-footer">
<div class="footer" style="text-align: center;">
🔗 GitHubリポジトリはこちら(<a href="https://github.com/ipusiron/whereshot" target="_blank" style="color: #007bff; text-decoration: none;">ipusiron/whereshot</a>)
</div>
</footer>
</div>
<!-- ヘルプモーダル -->
<div id="help-modal" class="modal" style="display: none;">
<div class="modal-content">
<span class="modal-close">×</span>
<h2>WhereShot 使用方法</h2>
<div class="help-content">
<h3>🚀 基本的な使い方</h3>
<ol>
<li><strong>画像をアップロード</strong>: ドラッグ&ドロップまたはファイル選択</li>
<li><strong>メタデータ確認</strong>: Exif情報を自動抽出・表示</li>
<li><strong>地図で位置確認</strong>: GPS情報があれば自動表示</li>
<li><strong>太陽位置計算</strong>: 影の方向と照合して時刻を検証</li>
<li><strong>外部データで詳細確認</strong>: 衛星画像や気象データと照合</li>
</ol>
<h3>🔒 プライバシー保護</h3>
<ul>
<li>すべての処理はブラウザ内で完結</li>
<li>画像・メタデータは外部送信されません</li>
<li>安全なOSINT調査が可能</li>
</ul>
<h3>⚠️ 注意事項</h3>
<ul>
<li>GPS情報がない画像は手動で位置指定が必要</li>
<li>改ざんされた画像のメタデータは信頼できません</li>
<li>複数の情報源で検証することを推奨</li>
</ul>
</div>
</div>
</div>
<!-- JavaScript ライブラリ -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.js" integrity="sha512-puJW3E/qXDqYp9IfhAI54BJEaWIfloJ7JWs7OeD5i6ruC9JZL1gERT1wjtwXFlh7CjE7ZJ+/vcRZRkIYIb6p4g==" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/exif-js/2.3.0/exif.min.js" integrity="sha512-xsoiisGNT6Dw2Le1Cocn5305Uje1pOYeSzrpO3RD9K+JTpVH9KqSXksXqur8cobTEKJcFz0COYq4723mzo88/Q==" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/suncalc/1.9.0/suncalc.min.js" integrity="sha512-F6rjAEKNMtM0aODcc/MdnAvhGxn7FCbAkKJ5FKba/fnD3gnN+LBEok326WAMdOhKQKYNr+j/tJEuV1PKwIfhCA==" crossorigin="anonymous"></script>
<!-- アプリケーションスクリプト -->
<script src="js/utils.js"></script>
<script src="js/exif-parser.js"></script>
<script src="js/datetime-estimator.js"></script>
<script src="js/sun-calculator.js"></script>
<script src="js/map-controller.js"></script>
<script src="js/main.js"></script>
<!-- 地図初期化管理スクリプト -->
<script>
// 地図初期化の状態管理
document.addEventListener('DOMContentLoaded', function() {
const mapContainer = document.getElementById('map');
// 地図初期化完了イベントリスナー
document.addEventListener('whereshot:mapInitialized', function() {
if (mapContainer) {
mapContainer.classList.remove('map-initializing');
mapContainer.classList.add('map-ready');
// 座標表示を更新
const mapCoordinates = document.getElementById('map-coordinates');
if (mapCoordinates) {
mapCoordinates.textContent = 'クリックして座標を取得';
}
console.log('[WhereShot] Map UI state updated to ready');
}
});
// 地図初期化失敗イベントリスナー
document.addEventListener('whereshot:mapInitializationFailed', function(e) {
if (mapContainer) {
mapContainer.classList.remove('map-initializing');
mapContainer.classList.add('map-error');
// エラーメッセージを表示
const mapCoordinates = document.getElementById('map-coordinates');
if (mapCoordinates) {
mapCoordinates.textContent = '地図の読み込みに失敗しました';
}
console.error('[WhereShot] Map initialization failed:', e.detail);
}
});
});
</script>
</body>
</html>