页面滚动时检测到图片减速效果不佳的技术求助
Hey there! Let's break down why your current implementation isn't giving you the expected scroll slowdown effect, and fix it properly.
What's Wrong With Your Current Code?
Your current approach uses transform: translateY to shift the image upward slower than the scroll speed. This makes the image appear to lag behind the scroll, but it doesn't actually slow down the page's scroll speed—that's why you're only seeing a tiny, unsatisfactory change. Additionally, your viewport detection function relies on offsetTop and offsetParent, which can be inaccurate for nested or positioned elements.
The Right Approach: Actually Adjust Scroll Speed
To make the page scroll slower when the image is in view, we need to intercept scroll events (mouse wheel, touch) and adjust how much the page scrolls. Here's how to do it:
Step 1: Reliable Viewport Detection
First, replace your elementInViewport2 function with a more accurate one using getBoundingClientRect(), which directly gives us the element's position relative to the viewport:
function isElementInViewport(el) { const rect = el.getBoundingClientRect(); // Check if any part of the element is visible in the viewport return ( rect.top < window.innerHeight && rect.bottom > 0 && rect.left < window.innerWidth && rect.right > 0 ); }
Step 2: Intercept Scroll Events to Slow Down
We'll listen for mouse wheel and touch events, and when the image is in view, we'll reduce the scroll distance by a custom factor (e.g., 50% slower):
document.addEventListener('DOMContentLoaded', function() { const targetImage = document.getElementById('slides'); const slowdownFactor = 0.5; // Adjust this: 0.1 = 10% speed, 0.9 = 90% speed // Handle mouse wheel scroll window.addEventListener('wheel', function(e) { if (isElementInViewport(targetImage)) { e.preventDefault(); // Stop default scroll behavior const adjustedScroll = e.deltaY * slowdownFactor; window.scrollBy({ top: adjustedScroll, behavior: 'auto' // Keep native scroll feel (use 'smooth' for gradual) }); } }, { passive: false }); // Required to use preventDefault() // Handle touch scroll (mobile) let touchStartY = 0; window.addEventListener('touchstart', function(e) { touchStartY = e.touches[0].clientY; }, { passive: true }); window.addEventListener('touchmove', function(e) { if (isElementInViewport(targetImage)) { e.preventDefault(); const touchCurrentY = e.touches[0].clientY; const adjustedScroll = (touchStartY - touchCurrentY) * slowdownFactor; window.scrollBy({ top: adjustedScroll, behavior: 'auto' }); touchStartY = touchCurrentY; } }, { passive: false }); });
Key Notes
passive: false: This is necessary forpreventDefault()to work—without it, browsers will ignore the default prevention (and throw a warning).- Slowdown Factor: Tweak
slowdownFactorto get the exact speed you want. A lower number means slower scrolling. - Inertia Handling: For scroll inertia (like when you flick scroll on mobile), this code handles the immediate touch input. If you need to smooth out residual inertia, you'd need to add additional logic to track scroll velocity over time.
Why This Works
Instead of shifting the image, we're directly controlling how far the page scrolls when the image is visible. This gives you the actual scroll slowdown effect you're looking for, not just a visual trick with transforms.
内容的提问来源于stack exchange,提问作者Sebastian Bochan

