I'm struggling to achieve a scrolling zoom effect similar to the website mentioned below, but I can't seem to get it to fully zoom.
Additionally, when I try to zoom in on a clipped shape or text while scrolling, the entire div ends up scrolling along with it.
I've set the zoom breakpoint to
document.body.clientWidth / imgElement.clientHeight
, but I'm unable to find an alternative solution.
Any suggestions would be greatly appreciated!
Thank you in advance.
https://i.sstatic.net/ZSBCo.jpg
View Sample Link of the Website
const zoomElement = document.querySelector('.zoom')
const afterZoomElement = document.querySelector('.afterzoom')
const imgElement = document.querySelector('h2')
const WIDTH = document.body.clientWidth
const HEIGHT = zoomElement.clientHeight
const IMAGE_WIDTH = imgElement.clientWidth
const IMAGE_HEIGHT = imgElement.clientHeight
const ZOOM_SPEED = 200 // Lower value for faster speed
const ZOOM_BREAKPOINT = WIDTH / IMAGE_HEIGHT // Point at which zooming should stop
const IMAGE_HEIGHT_MAX = IMAGE_HEIGHT * ZOOM_BREAKPOINT
const ABSOLUTE = ZOOM_BREAKPOINT * ZOOM_SPEED // Absolute position when element reaches maximum size
// Fade --------------------------------------------------------------------------------------
const FADE_SPEED = 400 // Lower value for faster speed
let fade = 1
let prev = 0
// -------------------------------------------------------------------------------------- Fade
function animate() {
let scroll = window.scrollY
let temp = scroll / ZOOM_SPEED
let zoom = temp > 1 ? temp : 1
if (zoom < ZOOM_BREAKPOINT) {
imgElement.style.transform = `scale(${zoom})`
zoomElement.style.top = '0px'
zoomElement.style.position = 'fixed'
} else {
imgElement.style.transform = `scale(${ZOOM_BREAKPOINT})`
zoomElement.style.position = 'absolute'
zoomElement.style.top = ABSOLUTE + 'px'
}
let dif = prev - scroll
if (zoom < ZOOM_BREAKPOINT - FADE_SPEED / ZOOM_SPEED) {
fade = 1
} else if (zoom > ZOOM_BREAKPOINT) {
fade = 0
} else {
fade += dif / FADE_SPEED
}
fadeElement.style.opacity = fade
prev = scroll
}
if ('scrollRestoration' in history) {
history.scrollRestoration = 'manual'
}
document.addEventListener('scroll', () => window.requestAnimationFrame(animate))
zoomElement.style.opacity = 1
afterZoomElement.style.top = ABSOLUTE + IMAGE_HEIGHT_MAX / 2 + HEIGHT / 2 + 'px'
body {
margin: 0;
}
h2 {
height: 100vh;
width: 100vw;
background-color: black;
display: flex;
justify-content: center;
align-items: center;
font-size: 5em;
text-transform: uppercase;
background: url(https://24.media.tumblr.com/tumblr_m87dri70zh1qzla33o1_500.gif);
background-size: cover;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.zoom {
height: 100vh;
width: 100%;
display: grid;
place-items: center;
position: fixed;
top: 0;
left: 0;
}
.afterzoom {
position: absolute;
height: 100vh;
width: 100%;
background: red;
overflow-x: auto;
}
h2{
font-size: 5em;
text-transform: uppercase;
background: url(https://24.media.tumblr.com/tumblr_m87dri70zh1qzla33o1_500.gif);
background-size: cover;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
<div class="zoom">
<h2>i</h2>
</div>
<div class="afterzoom">
<p>This content will appear after the above element is fully zoomed.</p>
</div>