|
128 | 128 | /* Add proper 3D transform classes */
|
129 | 129 | .preserve-3d { transform-style: preserve-3d; }
|
130 | 130 | .perspective-1000 { perspective: 1000px; }
|
| 131 | + .backface-hidden { backface-visibility: hidden; } |
131 | 132 | .rotate-y-180 { transform: rotateY(180deg); }
|
132 |
| - .translate-z-negative { transform: translateZ(-20px); } |
| 133 | + |
| 134 | + /* Visual flip container styling */ |
| 135 | + .visual-container { |
| 136 | + position: relative; |
| 137 | + width: 100%; |
| 138 | + height: 100%; |
| 139 | + transform-style: preserve-3d; |
| 140 | + transition: transform 0.8s; |
| 141 | + } |
| 142 | + |
| 143 | + .visual-xray, |
| 144 | + .visual-gradcam { |
| 145 | + position: absolute; |
| 146 | + width: 100%; |
| 147 | + height: 100%; |
| 148 | + backface-visibility: hidden; |
| 149 | + transition: all 0.6s ease; |
| 150 | + border-radius: 0.5rem; |
| 151 | + overflow: hidden; |
| 152 | + -webkit-backface-visibility: hidden; /* Fix for Safari */ |
| 153 | + } |
| 154 | + |
| 155 | + .visual-xray { |
| 156 | + z-index: 2; |
| 157 | + transform: rotateY(0deg); |
| 158 | + } |
| 159 | + |
| 160 | + .visual-gradcam { |
| 161 | + transform: rotateY(180deg); |
| 162 | + z-index: 1; |
| 163 | + } |
| 164 | + |
| 165 | + .flipped .visual-xray { |
| 166 | + z-index: 1; |
| 167 | + } |
| 168 | + |
| 169 | + .flipped .visual-gradcam { |
| 170 | + z-index: 2; |
| 171 | + } |
| 172 | + |
| 173 | + /* Ensure images properly fit within containers */ |
| 174 | + .visual-xray img, |
| 175 | + .visual-gradcam img { |
| 176 | + width: 100%; |
| 177 | + height: 100%; |
| 178 | + object-fit: cover; |
| 179 | + } |
133 | 180 | </style>
|
134 | 181 | </head>
|
135 | 182 | <body class="bg-white text-gray-800 font-sans">
|
@@ -162,13 +209,13 @@ <h1 class="text-4xl md:text-5xl font-extrabold mb-6 bg-gradient-to-br from-gray-
|
162 | 209 | <div class="lg:col-span-7 relative pb-[90%] lg:pb-0 lg:h-[500px] perspective-1000">
|
163 | 210 | <div id="visual-container" class="absolute w-4/5 h-4/5 top-[5%] left-[10%] preserve-3d animate-float">
|
164 | 211 | <!-- X-ray image (front) -->
|
165 |
| - <div class="visual-xray absolute inset-0 rounded-xl shadow-2xl transition-all duration-600 z-20 bg-gray-50 overflow-hidden"> |
| 212 | + <div class="visual-xray absolute inset-0 rounded-xl shadow-2xl transition-all duration-600 z-20 bg-gray-50 overflow-hidden backface-hidden flip-transition"> |
166 | 213 | <img src="./images/wrist-xray.jpg" alt="Wrist X-ray" class="w-full h-full object-cover scale-105"
|
167 | 214 | onerror="this.src='https://images.unsplash.com/photo-1583774198559-21876a208a23?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=600&q=80'">
|
168 | 215 | </div>
|
169 | 216 |
|
170 | 217 | <!-- Grad-CAM image (back) -->
|
171 |
| - <div class="visual-gradcam absolute inset-0 rounded-xl shadow-2xl transition-all duration-600 z-10 bg-gray-50 overflow-hidden transform translate-z-negative rotate-y-180"> |
| 218 | + <div class="visual-gradcam absolute inset-0 rounded-xl shadow-2xl transition-all duration-600 z-10 bg-gray-50 overflow-hidden transform translate-z-negative rotate-y-180 backface-hidden flip-transition"> |
172 | 219 | <img src="./images/wrist-gradcam.jpg" alt="Wrist X-ray with Grad-CAM visualization" class="w-full h-full object-cover scale-105"
|
173 | 220 | onerror="this.src='https://images.unsplash.com/photo-1583774198559-21876a208a23?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=600&q=80'">
|
174 | 221 | </div>
|
@@ -398,40 +445,55 @@ <h2 class="text-4xl font-bold mb-5 bg-gradient-to-r from-white to-white/80 bg-cl
|
398 | 445 |
|
399 | 446 | if (flipButton && visualContainer) {
|
400 | 447 | flipButton.addEventListener('click', () => {
|
401 |
| - if (!isFlipped) { |
| 448 | + isFlipped = !isFlipped; |
| 449 | + |
| 450 | + if (isFlipped) { |
402 | 451 | // Show heatmap (flip to Grad-CAM view)
|
403 |
| - visualXray.classList.add('transform', 'rotate-y-180', 'z-10'); |
404 |
| - visualXray.classList.remove('z-20'); |
| 452 | + visualContainer.style.transform = 'rotateY(180deg)'; |
| 453 | + visualContainer.classList.add('flipped'); |
405 | 454 |
|
406 |
| - visualGradcam.classList.add('z-20'); |
407 |
| - visualGradcam.classList.remove('transform', 'rotate-y-180', 'z-10'); |
| 455 | + // Force reflow to ensure animation plays properly |
| 456 | + void visualContainer.offsetWidth; |
408 | 457 |
|
409 |
| - flipButton.classList.remove('from-blue-500', 'to-blue-700'); |
410 |
| - flipButton.classList.add('from-red-400', 'to-red-500'); |
411 |
| - flipButton.innerHTML = ` |
412 |
| - <span class="relative z-10 flex items-center"> |
413 |
| - <span class="inline-block w-3 h-3 bg-white rounded-full mr-2 relative before:content-[''] before:absolute before:w-5 before:h-5 before:-inset-1 before:bg-white/30 before:rounded-full before:animate-pulse"></span> |
414 |
| - <span class="button-icon transform transition-transform duration-500"><i class="fas fa-eye"></i></span> |
415 |
| - Viewing Heatmap |
416 |
| - </span> |
417 |
| - <span class="absolute inset-0 bg-gradient-to-r from-transparent via-white/20 to-transparent -translate-x-full hover:translate-x-full transition-transform duration-700 z-0"></span> |
418 |
| - `; |
| 458 | + setTimeout(() => { |
| 459 | + flipButton.classList.remove('from-blue-500', 'to-blue-700'); |
| 460 | + flipButton.classList.add('from-red-400', 'to-red-500'); |
| 461 | + flipButton.innerHTML = ` |
| 462 | + <span class="relative z-10 flex items-center"> |
| 463 | + <span class="inline-block w-3 h-3 bg-white rounded-full mr-2 relative before:content-[''] before:absolute before:w-5 before:h-5 before:-inset-1 before:bg-white/30 before:rounded-full before:animate-pulse"></span> |
| 464 | + <span class="button-icon transform transition-transform duration-500"><i class="fas fa-eye"></i></span> |
| 465 | + Viewing Heatmap |
| 466 | + </span> |
| 467 | + <span class="absolute inset-0 bg-gradient-to-r from-transparent via-white/20 to-transparent -translate-x-full hover:translate-x-full transition-transform duration-700 z-0"></span> |
| 468 | + `; |
| 469 | + |
| 470 | + // Force a repaint of the GradCAM image to ensure it's visible |
| 471 | + const gradcamImg = visualGradcam.querySelector('img'); |
| 472 | + if (gradcamImg) { |
| 473 | + const currentSrc = gradcamImg.src; |
| 474 | + gradcamImg.src = ''; |
| 475 | + setTimeout(() => { |
| 476 | + gradcamImg.src = currentSrc; |
| 477 | + }, 10); |
| 478 | + } |
| 479 | + }, 300); |
419 | 480 | } else {
|
420 | 481 | // Show original (flip back to X-ray view)
|
421 |
| - visualXray.classList.remove('transform', 'rotate-y-180', 'z-10'); |
422 |
| - visualXray.classList.add('z-20'); |
| 482 | + visualContainer.style.transform = 'rotateY(0deg)'; |
| 483 | + visualContainer.classList.remove('flipped'); |
423 | 484 |
|
424 |
| - visualGradcam.classList.remove('z-20'); |
425 |
| - visualGradcam.classList.add('transform', 'rotate-y-180', 'z-10'); |
| 485 | + // Force reflow to ensure animation plays properly |
| 486 | + void visualContainer.offsetWidth; |
426 | 487 |
|
427 |
| - flipButton.classList.remove('from-red-400', 'to-red-500'); |
428 |
| - flipButton.classList.add('from-blue-500', 'to-blue-700'); |
429 |
| - flipButton.innerHTML = ` |
430 |
| - <span class="relative z-10"><i class="fas fa-sync-alt"></i> Toggle Heatmap View</span> |
431 |
| - <span class="absolute inset-0 bg-gradient-to-r from-transparent via-white/20 to-transparent -translate-x-full hover:translate-x-full transition-transform duration-700 z-0"></span> |
432 |
| - `; |
| 488 | + setTimeout(() => { |
| 489 | + flipButton.classList.remove('from-red-400', 'to-red-500'); |
| 490 | + flipButton.classList.add('from-blue-500', 'to-blue-700'); |
| 491 | + flipButton.innerHTML = ` |
| 492 | + <span class="relative z-10"><i class="fas fa-sync-alt"></i> Toggle Heatmap View</span> |
| 493 | + <span class="absolute inset-0 bg-gradient-to-r from-transparent via-white/20 to-transparent -translate-x-full hover:translate-x-full transition-transform duration-700 z-0"></span> |
| 494 | + `; |
| 495 | + }, 300); |
433 | 496 | }
|
434 |
| - isFlipped = !isFlipped; |
435 | 497 | });
|
436 | 498 | }
|
437 | 499 |
|
|
0 commit comments