|
74 | 74 | transform: translateY(-3px); |
75 | 75 | } |
76 | 76 |
|
77 | | - /* --- [CORE FIX] Slider Styling with Zoom --- */ |
| 77 | + /* --- [CORE FIX] Slider Styling with Wheel Zoom --- */ |
78 | 78 | .slider-container { |
79 | 79 | width: 100%; |
80 | 80 | aspect-ratio: 1 / 1; |
81 | | - overflow: hidden; /* 확대 시 이미지가 밖으로 나가지 않게 함 */ |
| 81 | + overflow: hidden; |
82 | 82 | border-radius: 12px; |
83 | 83 | position: relative; |
84 | 84 | background: #000; |
85 | | - cursor: crosshair; /* 줌 가능 커서 표시 */ |
| 85 | + cursor: zoom-in; /* 줌 가능 커서 표시 */ |
86 | 86 | } |
87 | 87 |
|
88 | 88 | /* 줌 애니메이션을 위한 래퍼 클래스 */ |
89 | 89 | .zoom-target { |
90 | 90 | width: 100%; |
91 | 91 | height: 100%; |
92 | 92 | transform-origin: center center; |
93 | | - transition: transform 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94); |
| 93 | + /* 휠 줌은 부드러운 반응을 위해 0.2s 정도의 빠른 트랜지션 사용 */ |
| 94 | + transition: transform 0.2s ease-out; |
94 | 95 | will-change: transform, transform-origin; |
95 | 96 | } |
96 | 97 |
|
97 | | - /* 마우스 오버 시 2.5배 확대 */ |
98 | | - .slider-container:hover .zoom-target { |
99 | | - transform: scale(2.5); |
100 | | - } |
| 98 | + /* 기존 :hover 시 강제 확대 CSS 제거됨 */ |
101 | 99 |
|
102 | 100 | img-comparison-slider { |
103 | 101 | --divider-width: 2px; |
@@ -350,7 +348,7 @@ <h3 class="title is-4" style="margin-bottom: 15px;"> |
350 | 348 | </div> |
351 | 349 |
|
352 | 350 | <div class="content has-text-centered is-size-6" style="color: #666; margin-top: 20px;"> |
353 | | - <i class="fas fa-search-plus"></i> Hover to <strong>Zoom</strong>, <i class="fas fa-arrows-alt-h"></i> Slide to compare. |
| 351 | + <i class="fas fa-search-plus"></i> Use <strong>Mouse Wheel</strong> to Zoom, <i class="fas fa-arrows-alt-h"></i> Slide to compare. |
354 | 352 | </div> |
355 | 353 |
|
356 | 354 | </div> |
@@ -571,25 +569,54 @@ <h4 class="title is-5" style="color: white; letter-spacing: 2px;">CMLab</h4> |
571 | 569 |
|
572 | 570 | containers.forEach(container => { |
573 | 571 | const target = container.querySelector('.zoom-target'); |
| 572 | + let scale = 1; |
| 573 | + const MIN_SCALE = 1; |
| 574 | + const MAX_SCALE = 5; |
| 575 | + const ZOOM_SPEED = 0.5; // Controls how fast the zoom happens per wheel tick |
| 576 | + |
| 577 | + // 1. Wheel Event Listener |
| 578 | + container.addEventListener('wheel', (e) => { |
| 579 | + // Prevent default scroll behavior of the page |
| 580 | + e.preventDefault(); |
| 581 | + |
| 582 | + // Check wheel direction: negative is up (zoom in), positive is down (zoom out) |
| 583 | + const direction = e.deltaY > 0 ? -1 : 1; |
| 584 | + |
| 585 | + // Calculate new scale |
| 586 | + const newScale = scale + (direction * ZOOM_SPEED); |
| 587 | + |
| 588 | + // Clamp scale value |
| 589 | + scale = Math.min(Math.max(newScale, MIN_SCALE), MAX_SCALE); |
574 | 590 |
|
| 591 | + // Apply scale |
| 592 | + target.style.transform = `scale(${scale})`; |
| 593 | + |
| 594 | + // Change cursor to indicate zooming out is possible if zoomed in |
| 595 | + container.style.cursor = scale > 1 ? 'move' : 'zoom-in'; |
| 596 | + |
| 597 | + }, { passive: false }); // Important: 'passive: false' allows preventDefault() |
| 598 | + |
| 599 | + // 2. Mouse Move Listener (For Panning) |
575 | 600 | container.addEventListener('mousemove', (e) => { |
576 | | - // Calculate container dimensions and mouse position |
577 | 601 | const rect = container.getBoundingClientRect(); |
578 | 602 |
|
579 | | - // Calculate Mouse X/Y as percentage (0-100) |
| 603 | + // Calculate percentage position |
580 | 604 | const x = ((e.clientX - rect.left) / rect.width) * 100; |
581 | 605 | const y = ((e.clientY - rect.top) / rect.height) * 100; |
582 | 606 |
|
583 | | - // Set transform origin to mouse position for "lens" effect |
| 607 | + // Update transform origin to follow mouse |
584 | 608 | target.style.transformOrigin = `${x}% ${y}%`; |
585 | 609 | }); |
586 | 610 |
|
587 | | - // Optional: Reset to center when mouse leaves for cleaner re-entry |
| 611 | + // 3. Mouse Leave Listener (Reset) |
588 | 612 | container.addEventListener('mouseleave', () => { |
589 | | - // Using timeout to match the CSS transition duration prevents jumpiness |
| 613 | + scale = 1; |
| 614 | + target.style.transform = `scale(1)`; |
| 615 | + container.style.cursor = 'zoom-in'; |
| 616 | + |
590 | 617 | setTimeout(() => { |
591 | 618 | target.style.transformOrigin = 'center center'; |
592 | | - }, 250); |
| 619 | + }, 200); |
593 | 620 | }); |
594 | 621 | }); |
595 | 622 | }); |
|
0 commit comments