Yang2001 commited on
Commit
bcb04f1
·
1 Parent(s): 3b7c4e4

feat: add gallery slider with auto-scroll and display FOV/distance

Browse files
Files changed (1) hide show
  1. index.html +125 -22
index.html CHANGED
@@ -417,6 +417,14 @@
417
  border-top: 1px solid var(--border);
418
  background: var(--surface);
419
  overflow: hidden;
 
 
 
 
 
 
 
 
420
  }
421
 
422
  .examples-grid {
@@ -425,8 +433,7 @@
425
  gap: 1rem;
426
  overflow-x: auto;
427
  overflow-y: hidden;
428
- padding-bottom: 0.5rem;
429
- scroll-behavior: smooth;
430
  scrollbar-width: none;
431
  -ms-overflow-style: none;
432
  }
@@ -436,14 +443,6 @@
436
  .examples-track {
437
  display: flex;
438
  gap: 1rem;
439
- animation: marquee-scroll 180s linear infinite;
440
- }
441
- .examples-track:hover {
442
- animation-play-state: paused;
443
- }
444
- @keyframes marquee-scroll {
445
- 0% { transform: translateX(0); }
446
- 100% { transform: translateX(-50%); }
447
  }
448
 
449
  .example-item {
@@ -460,6 +459,59 @@
460
  .example-item:hover {
461
  transform: translateY(-4px);
462
  border-color: var(--primary);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
463
  }
464
 
465
  .example-item img {
@@ -733,10 +785,15 @@
733
 
734
  <!-- Footer: Examples -->
735
  <div class="examples-drawer">
736
- <h4 style="font-size: 0.75rem; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 1rem;">Sample Gallery</h4>
 
 
737
  <div class="examples-grid" id="examples-grid">
738
  <!-- Injected via JS -->
739
  </div>
 
 
 
740
  </div>
741
  </div>
742
  </div>
@@ -1141,7 +1198,7 @@
1141
  'assets/images/s_20_img.webp'
1142
  ];
1143
 
1144
- // Create track element for seamless loop
1145
  const track = document.createElement('div');
1146
  track.className = 'examples-track';
1147
 
@@ -1163,7 +1220,6 @@
1163
  return div;
1164
  }
1165
 
1166
- // Add items twice for seamless loop
1167
  samples.forEach(path => track.appendChild(createItem(path)));
1168
  samples.forEach(path => track.appendChild(createItem(path)));
1169
 
@@ -1224,23 +1280,70 @@
1224
  setTimeout(() => t.style.display = 'none', 3000);
1225
  }
1226
 
1227
- // Enable mouse wheel horizontal scroll for examples gallery
1228
  const exGrid = document.getElementById('examples-grid');
1229
- let wheelTimeout = null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1230
  exGrid.addEventListener('wheel', (e) => {
1231
  if (Math.abs(e.deltaY) > 0) {
1232
  e.preventDefault();
1233
  exGrid.scrollLeft += e.deltaY;
1234
- // Pause animation while scrolling
1235
- const track = exGrid.querySelector('.examples-track');
1236
- if (track) track.style.animationPlayState = 'paused';
1237
- clearTimeout(wheelTimeout);
1238
- wheelTimeout = setTimeout(() => {
1239
- if (track) track.style.animationPlayState = 'running';
1240
- }, 1500);
1241
  }
1242
  }, { passive: false });
1243
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1244
  init();
1245
  </script>
1246
  </body>
 
417
  border-top: 1px solid var(--border);
418
  background: var(--surface);
419
  overflow: hidden;
420
+ position: relative;
421
+ }
422
+
423
+ .examples-header {
424
+ display: flex;
425
+ align-items: center;
426
+ justify-content: space-between;
427
+ margin-bottom: 1rem;
428
  }
429
 
430
  .examples-grid {
 
433
  gap: 1rem;
434
  overflow-x: auto;
435
  overflow-y: hidden;
436
+ padding-bottom: 1rem;
 
437
  scrollbar-width: none;
438
  -ms-overflow-style: none;
439
  }
 
443
  .examples-track {
444
  display: flex;
445
  gap: 1rem;
 
 
 
 
 
 
 
 
446
  }
447
 
448
  .example-item {
 
459
  .example-item:hover {
460
  transform: translateY(-4px);
461
  border-color: var(--primary);
462
+ box-shadow: 0 8px 24px rgba(99, 102, 241, 0.25);
463
+ }
464
+
465
+ /* Gallery Slider */
466
+ .gallery-slider-wrap {
467
+ margin-top: 0.75rem;
468
+ padding: 0 0.25rem;
469
+ }
470
+
471
+ .gallery-slider {
472
+ -webkit-appearance: none;
473
+ width: 100%;
474
+ height: 6px;
475
+ background: var(--border);
476
+ border-radius: 3px;
477
+ outline: none;
478
+ cursor: pointer;
479
+ transition: background 0.2s;
480
+ }
481
+
482
+ .gallery-slider:hover {
483
+ background: rgba(255, 255, 255, 0.12);
484
+ }
485
+
486
+ .gallery-slider::-webkit-slider-thumb {
487
+ -webkit-appearance: none;
488
+ width: 20px;
489
+ height: 20px;
490
+ background: linear-gradient(135deg, var(--primary), var(--accent));
491
+ border-radius: 50%;
492
+ cursor: grab;
493
+ box-shadow: 0 2px 8px rgba(99, 102, 241, 0.4);
494
+ transition: transform 0.2s, box-shadow 0.2s;
495
+ }
496
+
497
+ .gallery-slider::-webkit-slider-thumb:hover {
498
+ transform: scale(1.2);
499
+ box-shadow: 0 4px 16px rgba(99, 102, 241, 0.6);
500
+ }
501
+
502
+ .gallery-slider::-webkit-slider-thumb:active {
503
+ cursor: grabbing;
504
+ transform: scale(1.1);
505
+ }
506
+
507
+ .gallery-slider::-moz-range-thumb {
508
+ width: 20px;
509
+ height: 20px;
510
+ background: linear-gradient(135deg, var(--primary), var(--accent));
511
+ border-radius: 50%;
512
+ border: none;
513
+ cursor: grab;
514
+ box-shadow: 0 2px 8px rgba(99, 102, 241, 0.4);
515
  }
516
 
517
  .example-item img {
 
785
 
786
  <!-- Footer: Examples -->
787
  <div class="examples-drawer">
788
+ <div class="examples-header">
789
+ <h4 style="font-size: 0.75rem; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.1em;">Sample Gallery</h4>
790
+ </div>
791
  <div class="examples-grid" id="examples-grid">
792
  <!-- Injected via JS -->
793
  </div>
794
+ <div class="gallery-slider-wrap">
795
+ <input type="range" id="gallery-slider" class="gallery-slider" min="0" max="100" value="0">
796
+ </div>
797
  </div>
798
  </div>
799
  </div>
 
1198
  'assets/images/s_20_img.webp'
1199
  ];
1200
 
1201
+ // Create track element
1202
  const track = document.createElement('div');
1203
  track.className = 'examples-track';
1204
 
 
1220
  return div;
1221
  }
1222
 
 
1223
  samples.forEach(path => track.appendChild(createItem(path)));
1224
  samples.forEach(path => track.appendChild(createItem(path)));
1225
 
 
1280
  setTimeout(() => t.style.display = 'none', 3000);
1281
  }
1282
 
1283
+ // Gallery slider & scroll sync with auto-scroll
1284
  const exGrid = document.getElementById('examples-grid');
1285
+ const gallerySlider = document.getElementById('gallery-slider');
1286
+ let isSliderDragging = false;
1287
+ let autoScrollPaused = false;
1288
+ let pauseTimeout = null;
1289
+ const AUTO_SCROLL_SPEED = 0.5; // px per frame
1290
+
1291
+ function updateSliderFromScroll() {
1292
+ if (isSliderDragging) return;
1293
+ const maxScroll = exGrid.scrollWidth - exGrid.clientWidth;
1294
+ if (maxScroll <= 0) {
1295
+ gallerySlider.value = 0;
1296
+ return;
1297
+ }
1298
+ gallerySlider.value = (exGrid.scrollLeft / maxScroll) * 100;
1299
+ }
1300
+
1301
+ exGrid.addEventListener('scroll', updateSliderFromScroll);
1302
+
1303
+ gallerySlider.addEventListener('input', () => {
1304
+ isSliderDragging = true;
1305
+ autoScrollPaused = true;
1306
+ const maxScroll = exGrid.scrollWidth - exGrid.clientWidth;
1307
+ exGrid.scrollTo({ left: (gallerySlider.value / 100) * maxScroll, behavior: 'auto' });
1308
+ });
1309
+ gallerySlider.addEventListener('pointerup', () => { isSliderDragging = false; resumeAutoScrollLater(); });
1310
+ gallerySlider.addEventListener('change', () => { isSliderDragging = false; resumeAutoScrollLater(); });
1311
+
1312
+ // Mouse wheel horizontal scroll
1313
  exGrid.addEventListener('wheel', (e) => {
1314
  if (Math.abs(e.deltaY) > 0) {
1315
  e.preventDefault();
1316
  exGrid.scrollLeft += e.deltaY;
1317
+ autoScrollPaused = true;
1318
+ resumeAutoScrollLater();
 
 
 
 
 
1319
  }
1320
  }, { passive: false });
1321
 
1322
+ // Pause on hover
1323
+ exGrid.addEventListener('mouseenter', () => { autoScrollPaused = true; });
1324
+ exGrid.addEventListener('mouseleave', () => { resumeAutoScrollLater(500); });
1325
+
1326
+ function resumeAutoScrollLater(delay = 2000) {
1327
+ clearTimeout(pauseTimeout);
1328
+ pauseTimeout = setTimeout(() => { autoScrollPaused = false; }, delay);
1329
+ }
1330
+
1331
+ // Auto-scroll loop via requestAnimationFrame
1332
+ function autoScrollLoop() {
1333
+ if (!autoScrollPaused) {
1334
+ const maxScroll = exGrid.scrollWidth - exGrid.clientWidth;
1335
+ if (maxScroll > 0) {
1336
+ exGrid.scrollLeft += AUTO_SCROLL_SPEED;
1337
+ // Loop back to start
1338
+ if (exGrid.scrollLeft >= maxScroll) {
1339
+ exGrid.scrollLeft = 0;
1340
+ }
1341
+ }
1342
+ }
1343
+ requestAnimationFrame(autoScrollLoop);
1344
+ }
1345
+ requestAnimationFrame(autoScrollLoop);
1346
+
1347
  init();
1348
  </script>
1349
  </body>