Skip to content

Commit 351e505

Browse files
Merge pull request #4 from alok-devforge/gh-pages-tailwind
Add Grad-CAM visualization styles and flip functionality
2 parents 3097f02 + f0201be commit 351e505

File tree

2 files changed

+94
-29
lines changed

2 files changed

+94
-29
lines changed

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"liveServer.settings.port": 5502
3+
}

gradcam.html

Lines changed: 91 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,55 @@
128128
/* Add proper 3D transform classes */
129129
.preserve-3d { transform-style: preserve-3d; }
130130
.perspective-1000 { perspective: 1000px; }
131+
.backface-hidden { backface-visibility: hidden; }
131132
.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+
}
133180
</style>
134181
</head>
135182
<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-
162209
<div class="lg:col-span-7 relative pb-[90%] lg:pb-0 lg:h-[500px] perspective-1000">
163210
<div id="visual-container" class="absolute w-4/5 h-4/5 top-[5%] left-[10%] preserve-3d animate-float">
164211
<!-- 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">
166213
<img src="./images/wrist-xray.jpg" alt="Wrist X-ray" class="w-full h-full object-cover scale-105"
167214
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'">
168215
</div>
169216

170217
<!-- 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">
172219
<img src="./images/wrist-gradcam.jpg" alt="Wrist X-ray with Grad-CAM visualization" class="w-full h-full object-cover scale-105"
173220
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'">
174221
</div>
@@ -398,40 +445,55 @@ <h2 class="text-4xl font-bold mb-5 bg-gradient-to-r from-white to-white/80 bg-cl
398445

399446
if (flipButton && visualContainer) {
400447
flipButton.addEventListener('click', () => {
401-
if (!isFlipped) {
448+
isFlipped = !isFlipped;
449+
450+
if (isFlipped) {
402451
// 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');
405454

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;
408457

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);
419480
} else {
420481
// 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');
423484

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;
426487

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);
433496
}
434-
isFlipped = !isFlipped;
435497
});
436498
}
437499

0 commit comments

Comments
 (0)