yunyongsu commited on
Commit
bf00dfa
·
verified ·
1 Parent(s): 8f9aa58

트래킹 어플 만들어 줘

Browse files
Files changed (3) hide show
  1. index.html +28 -11
  2. tracking.html +72 -0
  3. tracking.js +169 -0
index.html CHANGED
@@ -4,16 +4,33 @@
4
  <meta charset="utf-8" />
5
  <meta name="viewport" content="width=device-width" />
6
  <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
 
9
  <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
4
  <meta charset="utf-8" />
5
  <meta name="viewport" content="width=device-width" />
6
  <title>My static Space</title>
7
+ <link rel="stylesheet" href="style.css" />
8
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
9
+ </head>
10
  <body>
11
+ <div class="card">
12
+ <h1>Triangle Tracking App</h1>
13
+ <p>Track your outdoor activities with simple interface.</p>
14
+ <a href="tracking.html" class="btn btn-primary">Go to Tracking</a>
15
+ <div class="features mt-3">
16
+ <h5>Features:</h5>
17
+ <ul>
18
+ <li>Path tracking on map</li>
19
+ <li>Distance, speed and duration</li>
20
+ <li>Activity history</li>
21
+ <li>Offline map support</li>
22
+ </ul>
23
+ </div>
24
+ </div>
25
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
26
+ <style>
27
+ .card {
28
+ max-width: 800px;
29
+ margin: 2rem auto;
30
+ padding: 2rem;
31
+ box-shadow: 0 0 10px rgba(0,0,0,0.1);
32
+ }
33
+ .btn { margin-top: 1rem; }
34
+ </style>
35
+ </body>
36
  </html>
tracking.html ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Triangle Tracking</title>
7
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
8
+ <script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"></script>
9
+ <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css" />
10
+ <style>
11
+ #map { height: 60vh; }
12
+ .stats-card { margin-bottom: 1rem; }
13
+ </style>
14
+ </head>
15
+ <body>
16
+ <div class="container-fluid p-4">
17
+ <h1 class="text-center mb-4">Triangle Tracking</h1>
18
+
19
+ <div class="row">
20
+ <div class="col-md-8">
21
+ <div id="map"></div>
22
+ </div>
23
+ <div class="col-md-4">
24
+ <div class="card stats-card">
25
+ <div class="card-body">
26
+ <h5 class="card-title">Current Session</h5>
27
+ <p class="mb-1">Distance: <span id="distance">0</span> km</p>
28
+ <p class="mb-1">Duration: <span id="duration">00:00:00</span></p>
29
+ <p class="mb-1">Speed: <span id="speed">0</span> km/h</p>
30
+ <p class="mb-1">Calories: <span id="calories">0</span> kcal</p>
31
+ </div>
32
+ </div>
33
+
34
+ <div class="card stats-card">
35
+ <div class="card-body">
36
+ <h5 class="card-title">Controls</h5>
37
+ <button id="startBtn" class="btn btn-success w-100 mb-2">Start Tracking</button>
38
+ <button id="stopBtn" class="btn btn-danger w-100 mb-2" disabled>Stop Tracking</button>
39
+ <button id="saveBtn" class="btn btn-primary w-100" disabled>Save Session</button>
40
+ </div>
41
+ </div>
42
+ </div>
43
+ </div>
44
+
45
+ <div class="row mt-4">
46
+ <div class="col-12">
47
+ <div class="card">
48
+ <div class="card-body">
49
+ <h5 class="card-title">Activity History</h5>
50
+ <table class="table">
51
+ <thead>
52
+ <tr>
53
+ <th>Date</th>
54
+ <th>Distance</th>
55
+ <th>Duration</th>
56
+ <th>Actions</th>
57
+ </tr>
58
+ </thead>
59
+ <tbody id="historyTable">
60
+ <!-- Will be populated by JS -->
61
+ </tbody>
62
+ </table>
63
+ </div>
64
+ </div>
65
+ </div>
66
+ </div>
67
+ </div>
68
+
69
+ <script src="tracking.js"></script>
70
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
71
+ </body>
72
+ </html>
tracking.js ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ```javascript
2
+ // Initialize map
3
+ const map = L.map('map').setView([37.5665, 126.9780], 13); // Default to Seoul
4
+ L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
5
+ attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
6
+ }).addTo(map);
7
+
8
+ // Tracking variables
9
+ let tracking = false;
10
+ let startTime = null;
11
+ let path = [];
12
+ let polyline = null;
13
+ let totalDistance = 0;
14
+ let watchId = null;
15
+
16
+ // DOM elements
17
+ const startBtn = document.getElementById('startBtn');
18
+ const stopBtn = document.getElementById('stopBtn');
19
+ const saveBtn = document.getElementById('saveBtn');
20
+ const distanceEl = document.getElementById('distance');
21
+ const durationEl = document.getElementById('duration');
22
+ const speedEl = document.getElementById('speed');
23
+ const caloriesEl = document.getElementById('calories');
24
+ const historyTable = document.getElementById('historyTable');
25
+
26
+ // Event listeners
27
+ startBtn.addEventListener('click', startTracking);
28
+ stopBtn.addEventListener('click', stopTracking);
29
+ saveBtn.addEventListener('click', saveSession);
30
+
31
+ function startTracking() {
32
+ tracking = true;
33
+ startTime = new Date();
34
+ path = [];
35
+ totalDistance = 0;
36
+
37
+ if (polyline) {
38
+ map.removeLayer(polyline);
39
+ }
40
+
41
+ startBtn.disabled = true;
42
+ stopBtn.disabled = false;
43
+ saveBtn.disabled = true;
44
+
45
+ watchId = navigator.geolocation.watchPosition(
46
+ updatePosition,
47
+ handleError,
48
+ { enableHighAccuracy: true, maximumAge: 10000, timeout: 5000 }
49
+ );
50
+
51
+ updateTimer();
52
+ timerInterval = setInterval(updateTimer, 1000);
53
+ }
54
+
55
+ function stopTracking() {
56
+ tracking = false;
57
+ if (watchId) {
58
+ navigator.geolocation.clearWatch(watchId);
59
+ }
60
+
61
+ startBtn.disabled = false;
62
+ stopBtn.disabled = true;
63
+ saveBtn.disabled = false;
64
+
65
+ clearInterval(timerInterval);
66
+ }
67
+
68
+ function saveSession() {
69
+ // Save to local storage
70
+ const sessions = JSON.parse(localStorage.getItem('trackingSessions') || '[]');
71
+ const duration = (new Date() - startTime) / 1000;
72
+
73
+ sessions.push({
74
+ date: new Date().toLocaleString(),
75
+ distance: totalDistance,
76
+ duration: formatTime(duration),
77
+ path: path
78
+ });
79
+
80
+ localStorage.setItem('trackingSessions', JSON.stringify(sessions));
81
+ updateHistoryTable();
82
+ saveBtn.disabled = true;
83
+ }
84
+
85
+ function updatePosition(position) {
86
+ const { latitude, longitude, speed, altitude } = position.coords;
87
+ const newPoint = [latitude, longitude];
88
+
89
+ // Add to path
90
+ path.push(newPoint);
91
+
92
+ // Update polyline
93
+ if (polyline) {
94
+ map.removeLayer(polyline);
95
+ }
96
+ polyline = L.polyline(path, {color: 'blue'}).addTo(map);
97
+
98
+ // Calculate distance
99
+ if (path.length > 1) {
100
+ const lastPoint = path[path.length - 2];
101
+ const distance = calculateDistance(lastPoint[0], lastPoint[1], latitude, longitude);
102
+ totalDistance += distance;
103
+ distanceEl.textContent = (totalDistance / 1000).toFixed(2);
104
+ }
105
+
106
+ // Update speed
107
+ const speedKmh = speed ? (speed * 3.6).toFixed(1) : 0;
108
+ speedEl.textContent = speedKmh;
109
+
110
+ // Estimate calories (very rough estimate)
111
+ const calories = (totalDistance / 1000) * 60; // 60kcal per km
112
+ caloriesEl.textContent = Math.round(calories);
113
+
114
+ // Center map on current position
115
+ map.setView(newPoint, map.getZoom());
116
+ }
117
+
118
+ function handleError(error) {
119
+ console.error('Geolocation error:', error.message);
120
+ if (tracking) {
121
+ stopTracking();
122
+ alert('Geolocation error: ' + error.message);
123
+ }
124
+ }
125
+
126
+ function updateTimer() {
127
+ if (!startTime) return;
128
+ const elapsed = (new Date() - startTime) / 1000;
129
+ durationEl.textContent = formatTime(elapsed);
130
+ }
131
+
132
+ function formatTime(seconds) {
133
+ const hrs = Math.floor(seconds / 3600);
134
+ const mins = Math.floor((seconds % 3600) / 60);
135
+ const secs = Math.floor(seconds % 60);
136
+ return `${hrs.toString().padStart(2, '0')}:${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
137
+ }
138
+
139
+ function calculateDistance(lat1, lon1, lat2, lon2) {
140
+ const R = 6371e3; // Earth radius in meters
141
+ const φ1 = lat1 * Math.PI/180;
142
+ const φ2 = lat2 * Math.PI/180;
143
+ const Δφ = (lat2-lat1) * Math.PI/180;
144
+ const Δλ = (lon2-lon1) * Math.PI/180;
145
+
146
+ const a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
147
+ Math.cos(φ1) * Math.cos(φ2) *
148
+ Math.sin(Δλ/2) * Math.sin(Δλ/2);
149
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
150
+
151
+ return R * c;
152
+ }
153
+
154
+ function updateHistoryTable() {
155
+ const sessions = JSON.parse(localStorage.getItem('trackingSessions') || '[]');
156
+
157
+ historyTable.innerHTML = sessions.map(session => `
158
+ <tr>
159
+ <td>${session.date}</td>
160
+ <td>${(session.distance / 1000).toFixed(2)} km</td>
161
+ <td>${session.duration}</td>
162
+ <td><button class="btn btn-sm btn-outline-primary">View</button></td>
163
+ </tr>
164
+ `).join('');
165
+ }
166
+
167
+ // Initialize
168
+ updateHistoryTable();
169
+ ```