I tried to make zoom in Zoom out on scroll. The element is zooming on scrolling but I want to make it(the zoomed element) go up once it reached the full width of the screen.
Here’s my code:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> .zoom{ height:100vh; width:100%; display:grid; place-items:center; position:fixed; top:0; left:0; background: url('img/bg.png'); } .afterzoom{ height: 200vh; background: red; } </style> </head> <body> <div class="zoom"> <!-- <h1>Zoom meeeee</h1> --> <img src="img/square.png" alt=""> </div> <div class="afterzoom"></div> <script> const zoomElement = document.querySelector(".zoom"); let zoom = 1; const ZOOM_SPEED = 0.1; document.addEventListener("wheel", function(e) { if(e.deltaY > 0){ if (zoomElement.style.transform >= `scale(5)`) { console.log("now scroll down"); return false; } zoomElement.style.transform = `scale(${zoom += ZOOM_SPEED})`; }else{ if (zoomElement.style.transform == `scale(1)`) { // console.log("minus"); return false; } zoomElement.style.transform = `scale(${zoom -= ZOOM_SPEED})`; } }); </script> </body> </html>
Fiddle: https://jsfiddle.net/mayureshpitale/6etpn0vs/3/
I am trying to make something like this: http://truegossiper.com/vilson17/
Advertisement
Answer
A bit of a different approach using the scroll event and window.scrollY
for positioning together with requestAnimationFrame
(RAF).
This also works, if the image (or other content) is not squared.
The problem with the wheel
event is, that it does not trigger when the user uses the scrollbar or arrow keys to scroll the page.
The problem with the scroll
event is, that it executes a lot… that’s why RAF is used, to only execute necessary zoom changes.
Keep in mind, this exact code works with the document width when the page is loaded. If the user resizes the window or changes the browsers zoom, the element will resize to the same scale as before. You could fix this with some extra code by using a ResizeObserver
. (Remove the existing event listener, resize the Image and execute parts of the code again, every time the document is resized…)
You will notice this, when you try to view the below snippet as full page.
const zoomElement = document.querySelector('.zoom') const fadeElement = document.querySelector('.fade') const afterZoomElement = document.querySelector('.afterzoom') const imgElement = document.querySelector('img') const WIDTH = document.body.clientWidth const HEIGHT = zoomElement.clientHeight const IMAGE_WIDTH = imgElement.clientWidth const IMAGE_HEIGHT = imgElement.clientHeight const ZOOM_SPEED = 100 // Lower is faster const ZOOM_BREAKPOINT = WIDTH / IMAGE_WIDTH // When it should stop zooming in const IMAGE_HEIGHT_MAX = IMAGE_HEIGHT * ZOOM_BREAKPOINT const ABSOLUTE = ZOOM_BREAKPOINT * ZOOM_SPEED // Absolute position, when the Element reached maximum size // Fade -------------------------------------------------------------------------------------- const FADE_SPEED = 500 // Lower is faster let fade = 1 let prev = 0 // -------------------------------------------------------------------------------------- Fade function anim() { let scroll = window.scrollY let temp = scroll / ZOOM_SPEED let zoom = temp > 1 ? temp : 1 // Only update the Elements scale, when we are below the breakpoint if (zoom < ZOOM_BREAKPOINT) { // Only scale the Image, so the Zoom element does not mess with the document width imgElement.style.transform = `scale(${zoom})` // Sets the Elements position to fixed, so it can resize without scrolling away zoomElement.style.top = '0px' zoomElement.style.position = 'fixed' } else { // Makes sure the Element always reaches Max Size imgElement.style.transform = `scale(${ZOOM_BREAKPOINT})` // Sets the elements position to absolute, so it will scroll with the rest of the document zoomElement.style.position = 'absolute' zoomElement.style.top = ABSOLUTE + 'px' } // Fade -------------------------------------------------------------------------------------- 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 // -------------------------------------------------------------------------------------- Fade } // Resets scroll position on every reload if ('scrollRestoration' in history) { history.scrollRestoration = 'manual' } document.addEventListener('scroll', () => window.requestAnimationFrame(anim)) // Fade -------------------------------------------------------------------------------------- zoomElement.style.opacity = 1 // -------------------------------------------------------------------------------------- Fade // Positions the afterZoom element right below the zoomed image afterZoomElement.style.top = ABSOLUTE + IMAGE_HEIGHT_MAX / 2 + HEIGHT / 2 + 'px'
body { margin: 0; } img { width: 150px; height: 150px; background-color: black; } .fade { height: 100vh; width: 100%; position: fixed; top: 0; left: 0; background: blue; } .zoom { height: 100vh; width: 100%; display: grid; place-items: center; position: fixed; top: 0; left: 0; } .afterzoom { position: absolute; height: 200vh; width: 100%; background: red; overflow-x: auto; }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <div class="fade"></div> <div class="zoom"> <img src="https://via.placeholder.com/150" alt=""> </div> <div class="afterzoom"> <p>This should appear after the above element is fully zoomed.</p> </div> </body>
I got a bit carried away during coding and added some fading-in and -out to the blue background. Not necessary, but looks nice. You can remove the Fade ----- Fade
parts of the code, without affecting functionality.
To alter zoom and fade speed, simply change the ZOOM_SPEED
and FADE_SPEED
variables.