feat: viewport-centered zoom - stay at your viewing position

Changed zoom behavior from "page-relative" to "viewport-relative":

Before:
- Zoomed from top of page causing perspective/depth effect
- Content appeared to move "through" the viewer
- Disorienting experience when scrolled down

After:
- Zooms from center of YOUR viewport (where you're looking)
- Content expands both above and below your position
- You stay at your original viewing point - no movement
- Like pinch-to-zoom: magnifies what you're currently viewing

Technical implementation:
1. Calculate viewport center relative to page (scrollTop + viewportHeight/2)
2. Convert to percentage of page height
3. Set transform-origin dynamically to that percentage
4. Apply scale transform from your viewing position
5. Adjust scroll to keep same content at viewport center

CSS changes:
- Default transform-origin: center center (was top center)
- Added transition for transform-origin: 0s (instant, no animation)
- Maintains smooth 0.08s linear transform transition

Result: Natural, stable zoom that feels like magnifying glass
This commit is contained in:
juanatsap
2025-11-12 12:00:21 +00:00
parent 405b88bac0
commit fce7d7b27e
2 changed files with 21 additions and 11 deletions
+3 -3
View File
@@ -551,8 +551,8 @@ iconify-icon {
min-height: auto; /* Changed from 100vh */
/* Zoom transform properties */
transform-origin: top center; /* Scale from top-center to maintain header alignment */
transition: transform 0.08s linear; /* Immediate, smooth analog response */
transform-origin: center center; /* Default origin, dynamically updated by JS to viewport center */
transition: transform 0.08s linear, transform-origin 0s; /* Smooth zoom, instant origin change */
will-change: transform; /* Hint browser to optimize for transforms */
}
@@ -3524,7 +3524,7 @@ html {
/* Solid blue color on hover - no gradient */
.zoom-control:hover .zoom-slider,
.zoom-slider:hover {
background: #3b82f6; /* solid blue */
background: rgba(145, 190, 236, 1); /* solid blue */
}
.zoom-slider:focus {
+18 -8
View File
@@ -330,20 +330,30 @@
// Convert percentage to scale factor (100 = 1.0, 150 = 1.5, etc.)
const newScale = zoomValue / 100;
// Calculate scale ratio for scroll adjustment
const scaleRatio = newScale / currentScale;
// Preserve visual position by adjusting scroll proportionally
// Zoom from the center of the viewport (user's current viewing position)
requestAnimationFrame(() => {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
const viewportHeight = window.innerHeight;
// Calculate the point in the page that's at the center of the viewport
const viewportCenter = scrollTop + (viewportHeight / 2);
// Calculate the percentage of the page height where the viewport center is
const pageHeight = cvPaper.scrollHeight;
const centerPercent = (viewportCenter / pageHeight) * 100;
// Set transform-origin to the viewport center so zoom happens from where you're looking
cvPaper.style.transformOrigin = `center ${centerPercent}%`;
// Apply transform
cvPaper.style.transform = `scale(${newScale})`;
// Adjust scroll position to maintain visual stability
// When zooming in (scaleRatio > 1), scroll more to keep same content visible
// When zooming out (scaleRatio < 1), scroll less
const newScrollTop = scrollTop * scaleRatio;
// Adjust scroll to keep the same content at viewport center
// The content position scales with the zoom, so adjust accordingly
const scaleRatio = newScale / currentScale;
const newViewportCenter = viewportCenter * scaleRatio;
const newScrollTop = newViewportCenter - (viewportHeight / 2);
window.scrollTo(0, newScrollTop);
// Update display