devarajns commited on
Commit
c89aeb6
·
verified ·
1 Parent(s): aa865af

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +576 -19
index.html CHANGED
@@ -1,19 +1,576 @@
1
- <!doctype html>
2
- <html>
3
- <head>
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>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>Eye Movement Tracker</title>
7
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
8
+ <style>
9
+ :root {
10
+ --primary-color: #5d69b2;
11
+ --secondary-color: #3a416f;
12
+ --accent-color: #ff7e5f;
13
+ --bg-color: #f5f7fa;
14
+ --text-color: #333;
15
+ }
16
+
17
+ * {
18
+ margin: 0;
19
+ padding: 0;
20
+ box-sizing: border-box;
21
+ }
22
+
23
+ body {
24
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
25
+ background-color: var(--bg-color);
26
+ color: var(--text-color);
27
+ display: flex;
28
+ flex-direction: column;
29
+ align-items: center;
30
+ min-height: 100vh;
31
+ padding: 2rem;
32
+ position: relative;
33
+ overflow-x: hidden;
34
+ }
35
+
36
+ header {
37
+ text-align: center;
38
+ margin-bottom: 2rem;
39
+ width: 100%;
40
+ }
41
+
42
+ h1 {
43
+ color: var(--primary-color);
44
+ margin-bottom: 0.5rem;
45
+ font-size: 2.2rem;
46
+ }
47
+
48
+ .subtitle {
49
+ color: var(--secondary-color);
50
+ opacity: 0.8;
51
+ margin-bottom: 1.5rem;
52
+ }
53
+
54
+ .tracker-container {
55
+ display: flex;
56
+ flex-direction: column;
57
+ align-items: center;
58
+ width: 100%;
59
+ max-width: 800px;
60
+ gap: 2rem;
61
+ }
62
+
63
+ .face-container {
64
+ position: relative;
65
+ width: 300px;
66
+ height: 300px;
67
+ background-color: #fff;
68
+ border-radius: 50%;
69
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
70
+ display: flex;
71
+ justify-content: center;
72
+ align-items: center;
73
+ margin-bottom: 1rem;
74
+ transition: transform 0.3s ease;
75
+ }
76
+
77
+ .face-container:hover {
78
+ transform: scale(1.02);
79
+ }
80
+
81
+ .eyes-wrapper {
82
+ display: flex;
83
+ gap: 60px;
84
+ position: relative;
85
+ top: -20px;
86
+ }
87
+
88
+ .eye {
89
+ width: 60px;
90
+ height: 60px;
91
+ background-color: #fff;
92
+ border-radius: 50%;
93
+ position: relative;
94
+ box-shadow: inset 0 0 15px rgba(0, 0, 0, 0.2);
95
+ overflow: hidden;
96
+ }
97
+
98
+ .pupil {
99
+ width: 30px;
100
+ height: 30px;
101
+ background-color: var(--secondary-color);
102
+ border-radius: 50%;
103
+ position: absolute;
104
+ top: 15px;
105
+ left: 15px;
106
+ transition: all 0.1s ease;
107
+ }
108
+
109
+ .metrics-container {
110
+ display: flex;
111
+ flex-wrap: wrap;
112
+ gap: 1rem;
113
+ justify-content: center;
114
+ width: 100%;
115
+ }
116
+
117
+ .metric-card {
118
+ background-color: white;
119
+ border-radius: 12px;
120
+ padding: 1.5rem;
121
+ min-width: 200px;
122
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
123
+ flex-grow: 1;
124
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
125
+ }
126
+
127
+ .metric-card:hover {
128
+ transform: translateY(-5px);
129
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
130
+ }
131
+
132
+ .metric-title {
133
+ color: var(--primary-color);
134
+ font-size: 0.9rem;
135
+ text-transform: uppercase;
136
+ letter-spacing: 1px;
137
+ margin-bottom: 0.5rem;
138
+ display: flex;
139
+ align-items: center;
140
+ gap: 0.5rem;
141
+ }
142
+
143
+ .metric-value {
144
+ font-size: 1.8rem;
145
+ font-weight: bold;
146
+ color: var(--secondary-color);
147
+ }
148
+
149
+ .metric-unit {
150
+ font-size: 0.9rem;
151
+ color: #888;
152
+ margin-left: 0.3rem;
153
+ }
154
+
155
+ .chart-container {
156
+ width: 100%;
157
+ height: 200px;
158
+ background-color: white;
159
+ border-radius: 12px;
160
+ padding: 1rem;
161
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
162
+ position: relative;
163
+ overflow: hidden;
164
+ }
165
+
166
+ canvas {
167
+ width: 100%;
168
+ height: 100%;
169
+ }
170
+
171
+ .controls {
172
+ display: flex;
173
+ gap: 1rem;
174
+ margin-top: 1rem;
175
+ }
176
+
177
+ button {
178
+ padding: 0.8rem 1.5rem;
179
+ background-color: var(--primary-color);
180
+ color: white;
181
+ border: none;
182
+ border-radius: 8px;
183
+ cursor: pointer;
184
+ font-weight: 600;
185
+ transition: all 0.3s ease;
186
+ display: flex;
187
+ align-items: center;
188
+ gap: 0.5rem;
189
+ }
190
+
191
+ button:hover {
192
+ background-color: var(--secondary-color);
193
+ transform: translateY(-2px);
194
+ }
195
+
196
+ button.secondary {
197
+ background-color: white;
198
+ color: var(--primary-color);
199
+ border: 1px solid #ddd;
200
+ }
201
+
202
+ button.secondary:hover {
203
+ background-color: #f0f0f0;
204
+ }
205
+
206
+ .data-points {
207
+ position: absolute;
208
+ top: 20px;
209
+ right: 20px;
210
+ width: 15px;
211
+ height: 15px;
212
+ background-color: var(--accent-color);
213
+ border-radius: 50%;
214
+ opacity: 0;
215
+ pointer-events: none;
216
+ transition: opacity 0.3s ease;
217
+ }
218
+
219
+ footer {
220
+ margin-top: 3rem;
221
+ text-align: center;
222
+ color: #888;
223
+ font-size: 0.9rem;
224
+ }
225
+
226
+ @media (max-width: 600px) {
227
+ .tracker-container {
228
+ gap: 1rem;
229
+ }
230
+
231
+ .face-container {
232
+ width: 250px;
233
+ height: 250px;
234
+ }
235
+
236
+ .eyes-wrapper {
237
+ gap: 40px;
238
+ }
239
+
240
+ .eye {
241
+ width: 50px;
242
+ height: 50px;
243
+ }
244
+
245
+ .pupil {
246
+ width: 25px;
247
+ height: 25px;
248
+ top: 12.5px;
249
+ left: 12.5px;
250
+ }
251
+
252
+ .metric-card {
253
+ min-width: 150px;
254
+ padding: 1rem;
255
+ }
256
+
257
+ .metric-value {
258
+ font-size: 1.5rem;
259
+ }
260
+ }
261
+ </style>
262
+ </head>
263
+ <body>
264
+ <header>
265
+ <h1><i class="fas fa-eye"></i> Eye Movement Tracker</h1>
266
+ <p class="subtitle">Interactive demonstration of gaze tracking using mouse position</p>
267
+ </header>
268
+
269
+ <div class="tracker-container">
270
+ <div class="face-container">
271
+ <div class="eyes-wrapper">
272
+ <div class="eye">
273
+ <div class="pupil" id="left-pupil"></div>
274
+ </div>
275
+ <div class="eye">
276
+ <div class="pupil" id="right-pupil"></div>
277
+ </div>
278
+ </div>
279
+ <div class="data-points" id="data-point"></div>
280
+ </div>
281
+
282
+ <div class="metrics-container">
283
+ <div class="metric-card">
284
+ <div class="metric-title">
285
+ <i class="fas fa-crosshairs"></i> Gaze Position
286
+ </div>
287
+ <div class="metric-value" id="gaze-position">
288
+ <span id="gaze-x">0</span>, <span id="gaze-y">0</span>
289
+ </div>
290
+ </div>
291
+
292
+ <div class="metric-card">
293
+ <div class="metric-title">
294
+ <i class="fas fa-running"></i> Movement Speed
295
+ </div>
296
+ <div class="metric-value" id="movement-speed">0<span class="metric-unit">px/s</span></div>
297
+ </div>
298
+
299
+ <div class="metric-card">
300
+ <div class="metric-title">
301
+ <i class="fas fa-history"></i> Time Focused
302
+ </div>
303
+ <div class="metric-value" id="time-focused">0<span class="metric-unit">s</span></div>
304
+ </div>
305
+
306
+ <div class="metric-card">
307
+ <div class="metric-title">
308
+ <i class="fas fa-bullseye"></i> Fixations
309
+ </div>
310
+ <div class="metric-value" id="fixation-count">0</div>
311
+ </div>
312
+ </div>
313
+
314
+ <div class="chart-container">
315
+ <canvas id="gaze-chart"></canvas>
316
+ </div>
317
+
318
+ <div class="controls">
319
+ <button id="start-btn"><i class="fas fa-play"></i> Start Tracking</button>
320
+ <button id="reset-btn" class="secondary"><i class="fas fa-redo"></i> Reset</button>
321
+ <button id="heatmap-btn" class="secondary"><i class="fas fa-fire"></i> Show Heatmap</button>
322
+ </div>
323
+ </div>
324
+
325
+ <footer>
326
+ <p>Eye Movement Tracker &copy; 2025 | Uses mouse position to simulate eye tracking</p>
327
+ </footer>
328
+
329
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
330
+ <script>
331
+ document.addEventListener('DOMContentLoaded', function() {
332
+ // Elements
333
+ const leftPupil = document.getElementById('left-pupil');
334
+ const rightPupil = document.getElementById('right-pupil');
335
+ const gazeX = document.getElementById('gaze-x');
336
+ const gazeY = document.getElementById('gaze-y');
337
+ const movementSpeed = document.getElementById('movement-speed');
338
+ const timeFocused = document.getElementById('time-focused');
339
+ const fixationCount = document.getElementById('fixation-count');
340
+ const startBtn = document.getElementById('start-btn');
341
+ const resetBtn = document.getElementById('reset-btn');
342
+ const heatmapBtn = document.getElementById('heatmap-btn');
343
+ const dataPoint = document.getElementById('data-point');
344
+ const faceContainer = document.querySelector('.face-container');
345
+
346
+ // Variables
347
+ let trackingActive = false;
348
+ let startTime = 0;
349
+ let lastPosition = { x: 0, y: 0 };
350
+ let lastTime = 0;
351
+ let currentSpeed = 0;
352
+ let fixations = 0;
353
+ let fixationStartTime = 0;
354
+ let isFixated = false;
355
+ let gazeHistory = [];
356
+ let heatmapPoints = [];
357
+
358
+ // Chart setup
359
+ const ctx = document.getElementById('gaze-chart').getContext('2d');
360
+ const gazeChart = new Chart(ctx, {
361
+ type: 'line',
362
+ data: {
363
+ labels: [],
364
+ datasets: [{
365
+ label: 'Gaze Movement Speed (px/s)',
366
+ data: [],
367
+ borderColor: '#5d69b2',
368
+ backgroundColor: 'rgba(93, 105, 178, 0.1)',
369
+ tension: 0.4,
370
+ fill: true
371
+ }]
372
+ },
373
+ options: {
374
+ responsive: true,
375
+ maintainAspectRatio: false,
376
+ scales: {
377
+ y: {
378
+ beginAtZero: true
379
+ }
380
+ },
381
+ animation: {
382
+ duration: 0
383
+ }
384
+ }
385
+ });
386
+
387
+ // Helper functions
388
+ function calculatePupilPosition(eye, event) {
389
+ const eyeRect = eye.getBoundingClientRect();
390
+ const eyeCenterX = eyeRect.left + eyeRect.width / 2;
391
+ const eyeCenterY = eyeRect.top + eyeRect.height / 2;
392
+
393
+ const angle = Math.atan2(event.clientY - eyeCenterY, event.clientX - eyeCenterX);
394
+ const distance = Math.min(15, Math.sqrt(
395
+ Math.pow(event.clientX - eyeCenterX, 2) +
396
+ Math.pow(event.clientY - eyeCenterY, 2)
397
+ ) / 10);
398
+
399
+ const x = distance * Math.cos(angle);
400
+ const y = distance * Math.sin(angle);
401
+
402
+ return { x, y };
403
+ }
404
+
405
+ function updateMetrics(event) {
406
+ const now = Date.now();
407
+ const timeElapsed = (now - lastTime) / 1000;
408
+
409
+ if (timeElapsed > 0) {
410
+ const dx = event.clientX - lastPosition.x;
411
+ const dy = event.clientY - lastPosition.y;
412
+ const distance = Math.sqrt(dx * dx + dy * dy);
413
+ currentSpeed = distance / timeElapsed;
414
+
415
+ // Check for fixation (hovering in the same area)
416
+ if (distance < 15) { // 15px threshold for fixation
417
+ if (!isFixated) {
418
+ isFixated = true;
419
+ fixationStartTime = now;
420
+ }
421
+
422
+ // If fixation lasts more than 200ms, count it
423
+ if (isFixated && now - fixationStartTime > 200 && !fixationCounted) {
424
+ fixations++;
425
+ fixationCount.textContent = fixations;
426
+ fixationCounted = true;
427
+
428
+ // Show fixation point
429
+ if (dataPoint) {
430
+ dataPoint.style.left = `${event.clientX - faceContainer.getBoundingClientRect().left - 7.5}px`;
431
+ dataPoint.style.top = `${event.clientY - faceContainer.getBoundingClientRect().top - 7.5}px`;
432
+ dataPoint.style.opacity = '0.7';
433
+ setTimeout(() => {
434
+ dataPoint.style.opacity = '0';
435
+ }, 500);
436
+ }
437
+
438
+ // Store heatmap point
439
+ const rect = faceContainer.getBoundingClientRect();
440
+ const x = event.clientX - rect.left;
441
+ const y = event.clientY - rect.top;
442
+ heatmapPoints.push({ x, y });
443
+ }
444
+ } else {
445
+ isFixated = false;
446
+ fixationCounted = false;
447
+ }
448
+ }
449
+
450
+ // Update metrics display
451
+ movementSpeed.textContent = Math.round(currentSpeed);
452
+ timeFocused.textContent = Math.round((now - startTime) / 1000);
453
+
454
+ // Update chart data
455
+ if (gazeHistory.length > 50) {
456
+ gazeHistory.shift();
457
+ gazeChart.data.labels.shift();
458
+ gazeChart.data.datasets[0].data.shift();
459
+ }
460
+
461
+ gazeHistory.push(currentSpeed);
462
+ gazeChart.data.labels.push('');
463
+ gazeChart.data.datasets[0].data.push(currentSpeed);
464
+ gazeChart.update();
465
+
466
+ // Update last position and time
467
+ lastPosition = { x: event.clientX, y: event.clientY };
468
+ lastTime = now;
469
+ }
470
+
471
+ function startTracking() {
472
+ trackingActive = true;
473
+ startTime = Date.now();
474
+ startBtn.innerHTML = '<i class="fas fa-pause"></i> Pause Tracking';
475
+ startBtn.style.backgroundColor = '#ff7e5f';
476
+ }
477
+
478
+ function pauseTracking() {
479
+ trackingActive = false;
480
+ startBtn.innerHTML = '<i class="fas fa-play"></i> Resume Tracking';
481
+ startBtn.style.backgroundColor = '#5d69b2';
482
+ }
483
+
484
+ function resetTracking() {
485
+ pauseTracking();
486
+ startTime = 0;
487
+ currentSpeed = 0;
488
+ fixations = 0;
489
+ gazeHistory = [];
490
+ heatmapPoints = [];
491
+
492
+ // Reset metrics display
493
+ gazeX.textContent = '0';
494
+ gazeY.textContent = '0';
495
+ movementSpeed.textContent = '0';
496
+ timeFocused.textContent = '0';
497
+ fixationCount.textContent = '0';
498
+
499
+ // Reset chart
500
+ gazeChart.data.labels = [];
501
+ gazeChart.data.datasets[0].data = [];
502
+ gazeChart.update();
503
+
504
+ // Reset pupils to center
505
+ leftPupil.style.transform = 'translate(0, 0)';
506
+ rightPupil.style.transform = 'translate(0, 0)';
507
+ }
508
+
509
+ function showHeatmap() {
510
+ const heatmapOverlay = document.createElement('div');
511
+ heatmapOverlay.style.position = 'absolute';
512
+ heatmapOverlay.style.top = '0';
513
+ heatmapOverlay.style.left = '0';
514
+ heatmapOverlay.style.width = '100%';
515
+ heatmapOverlay.style.height = '100%';
516
+ heatmapOverlay.style.background = 'rgba(255, 126, 95, 0.1)';
517
+ heatmapOverlay.style.borderRadius = '50%';
518
+
519
+ heatmapPoints.forEach(point => {
520
+ const heatPoint = document.createElement('div');
521
+ heatPoint.style.position = 'absolute';
522
+ heatPoint.style.width = '20px';
523
+ heatPoint.style.height = '20px';
524
+ heatPoint.style.background = 'rgba(255, 126, 95, 0.3)';
525
+ heatPoint.style.borderRadius = '50%';
526
+ heatPoint.style.left = `${point.x - 10}px`;
527
+ heatPoint.style.top = `${point.y - 10}px`;
528
+ heatPoint.style.pointerEvents = 'none';
529
+ heatmapOverlay.appendChild(heatPoint);
530
+ });
531
+
532
+ faceContainer.appendChild(heatmapOverlay);
533
+
534
+ setTimeout(() => {
535
+ faceContainer.removeChild(heatmapOverlay);
536
+ }, 5000);
537
+ }
538
+
539
+ // Event listeners
540
+ document.addEventListener('mousemove', function(event) {
541
+ // Update gaze position display
542
+ gazeX.textContent = event.clientX;
543
+ gazeY.textContent = event.clientY;
544
+
545
+ // Calculate pupil positions
546
+ const leftPupilPos = calculatePupilPosition(leftPupil.parentElement, event);
547
+ const rightPupilPos = calculatePupilPosition(rightPupil.parentElement, event);
548
+
549
+ // Apply pupil positions
550
+ leftPupil.style.transform = `translate(${leftPupilPos.x}px, ${leftPupilPos.y}px)`;
551
+ rightPupil.style.transform = `translate(${rightPupilPos.x}px, ${rightPupilPos.y}px)`;
552
+
553
+ // Update metrics if tracking is active
554
+ if (trackingActive) {
555
+ updateMetrics(event);
556
+ }
557
+ });
558
+
559
+ startBtn.addEventListener('click', function() {
560
+ if (trackingActive) {
561
+ pauseTracking();
562
+ } else {
563
+ startTracking();
564
+ }
565
+ });
566
+
567
+ resetBtn.addEventListener('click', resetTracking);
568
+
569
+ heatmapBtn.addEventListener('click', showHeatmap);
570
+
571
+ // Initialize
572
+ resetTracking();
573
+ });
574
+ </script>
575
+ </body>
576
+ </html>