|
60 | 60 | --md-sys-color-outline: #8c9288; |
61 | 61 | } |
62 | 62 |
|
63 | | -:root, md-filled-button, md-outlined-button, md-switch { |
| 63 | +:root, md-filled-button, md-outlined-button, md-switch, md-icon-button { |
64 | 64 | --md-ref-typeface-brand: 'Google Sans Flex', 'Outfit', sans-serif; |
65 | 65 | --md-ref-typeface-plain: 'Google Sans Flex', 'Outfit', sans-serif; |
66 | 66 | --md-sys-typescale-label-large-font: 'Google Sans Flex', 'Outfit', sans-serif; |
|
143 | 143 | margin: 1rem 0 3rem 0; |
144 | 144 | } |
145 | 145 |
|
| 146 | +.carousel-container { |
| 147 | + position: relative; |
| 148 | +} |
| 149 | + |
| 150 | +.nav-btn { |
| 151 | + position: absolute; |
| 152 | + top: 50%; |
| 153 | + transform: translateY(-50%); |
| 154 | + z-index: 10; |
| 155 | + background-color: var(--md-sys-color-surface-variant); |
| 156 | + border-radius: 50%; |
| 157 | +} |
| 158 | + |
| 159 | +.prev-btn { |
| 160 | + left: 2vw; |
| 161 | +} |
| 162 | + |
| 163 | +.next-btn { |
| 164 | + right: 2vw; |
| 165 | +} |
| 166 | + |
146 | 167 | .carousel { |
147 | 168 | display: flex; |
148 | 169 | overflow-x: auto; |
|
167 | 188 | object-fit: cover; |
168 | 189 | flex-shrink: 0; |
169 | 190 | box-shadow: 0 4px 12px rgba(0,0,0,0.1); |
| 191 | + user-select: none; |
170 | 192 | } |
171 | 193 |
|
172 | 194 | .grid { |
|
314 | 336 | opacity: 0.8; |
315 | 337 | } |
316 | 338 |
|
| 339 | +@media (max-width: 800px) { |
| 340 | + .nav-btn { |
| 341 | + display: none; |
| 342 | + } |
| 343 | +} |
| 344 | + |
317 | 345 | @media (max-width: 600px) { |
318 | 346 | .top-bar { |
319 | 347 | padding: 1rem; |
@@ -352,10 +380,18 @@ <h1>XMusic</h1> |
352 | 380 |
|
353 | 381 | <div class="carousel-wrapper"> |
354 | 382 | <h2 style="text-align: center; margin-bottom: 1rem;">Showcase</h2> |
355 | | - <div class="carousel"> |
356 | | - <img src="website/assets/ss1.jpg" alt="Screenshot 1"> |
357 | | - <img src="website/assets/ss2.jpg" alt="Screenshot 2"> |
358 | | - <img src="website/assets/ss3.jpg" alt="Screenshot 3"> |
| 383 | + <div class="carousel-container"> |
| 384 | + <md-icon-button class="nav-btn prev-btn"> |
| 385 | + <span class="material-symbols-outlined">chevron_left</span> |
| 386 | + </md-icon-button> |
| 387 | + <div class="carousel"> |
| 388 | + <img src="website/assets/ss1.jpg" alt="Screenshot 1"> |
| 389 | + <img src="website/assets/ss2.jpg" alt="Screenshot 2"> |
| 390 | + <img src="website/assets/ss3.jpg" alt="Screenshot 3"> |
| 391 | + </div> |
| 392 | + <md-icon-button class="nav-btn next-btn"> |
| 393 | + <span class="material-symbols-outlined">chevron_right</span> |
| 394 | + </md-icon-button> |
359 | 395 | </div> |
360 | 396 | </div> |
361 | 397 |
|
@@ -489,6 +525,50 @@ <h2 style="margin-top: 0; text-align: center;">Credits & Special Thanks</h2> |
489 | 525 | htmlElement.setAttribute('data-theme', 'light'); |
490 | 526 | } |
491 | 527 | }); |
| 528 | + |
| 529 | + const carousel = document.querySelector('.carousel'); |
| 530 | + const prevBtn = document.querySelector('.prev-btn'); |
| 531 | + const nextBtn = document.querySelector('.next-btn'); |
| 532 | + |
| 533 | + let isDown = false; |
| 534 | + let startX; |
| 535 | + let scrollLeft; |
| 536 | + |
| 537 | + carousel.addEventListener('mousedown', (e) => { |
| 538 | + isDown = true; |
| 539 | + carousel.style.cursor = 'grabbing'; |
| 540 | + carousel.style.scrollSnapType = 'none'; |
| 541 | + startX = e.pageX - carousel.offsetLeft; |
| 542 | + scrollLeft = carousel.scrollLeft; |
| 543 | + }); |
| 544 | + |
| 545 | + carousel.addEventListener('mouseleave', () => { |
| 546 | + isDown = false; |
| 547 | + carousel.style.cursor = 'auto'; |
| 548 | + carousel.style.scrollSnapType = 'x mandatory'; |
| 549 | + }); |
| 550 | + |
| 551 | + carousel.addEventListener('mouseup', () => { |
| 552 | + isDown = false; |
| 553 | + carousel.style.cursor = 'auto'; |
| 554 | + carousel.style.scrollSnapType = 'x mandatory'; |
| 555 | + }); |
| 556 | + |
| 557 | + carousel.addEventListener('mousemove', (e) => { |
| 558 | + if (!isDown) return; |
| 559 | + e.preventDefault(); |
| 560 | + const x = e.pageX - carousel.offsetLeft; |
| 561 | + const walk = (x - startX) * 1.5; |
| 562 | + carousel.scrollLeft = scrollLeft - walk; |
| 563 | + }); |
| 564 | + |
| 565 | + prevBtn.addEventListener('click', () => { |
| 566 | + carousel.scrollBy({ left: -carousel.clientWidth * 0.8, behavior: 'smooth' }); |
| 567 | + }); |
| 568 | + |
| 569 | + nextBtn.addEventListener('click', () => { |
| 570 | + carousel.scrollBy({ left: carousel.clientWidth * 0.8, behavior: 'smooth' }); |
| 571 | + }); |
492 | 572 | </script> |
493 | 573 |
|
494 | 574 | </body> |
|
0 commit comments