多水平滚动区域图片懒加载异常:视口底/右侧触发逻辑失效
需求目标
实现图片懒加载:当图片靠近视口底部或右侧20%范围时加载,让用户滚动时感知图片“始终存在”——查看当前图片时,右侧及下方图片在屏幕外预加载。
问题现象
- 方案1:视口底部触发逻辑正常,但右侧触发失效——图片刚接触视口右侧即加载,未按设置的20%提前触发;
- 方案2:视口右侧触发逻辑正常,但底部触发失效——页面加载时所有图片已完成加载。
代码实现
JavaScript
import React, {useEffect} from 'react'; import './test.css'; // dummy test data const coffeeShops = [ { title: 'Coffee Shop 1', photos: [ 'picture 1 of Coffee Shop 1', 'picture 2 of Coffee Shop 1', 'picture 3 of Coffee Shop 1', 'picture 4 of Coffee Shop 1' ] }, { title: 'Coffee Shop 2', photos: [ 'picture 1 of Coffee Shop 2', 'picture 2 of Coffee Shop 2', 'picture 3 of Coffee Shop 2', 'picture 4 of Coffee Shop 2' ] }, { title: 'Coffee Shop 3', photos: [ 'picture 1 of Coffee Shop 3', 'picture 2 of Coffee Shop 3', 'picture 3 of Coffee Shop 3', 'picture 4 of Coffee Shop 3' ] }, { title: 'Coffee Shop 4', photos: [ 'picture 1 of Coffee Shop 4', 'picture 2 of Coffee Shop 4', 'picture 3 of Coffee Shop 4', 'picture 4 of Coffee Shop 4' ] } ] export const Test = () => { useEffect(() => { const svgs = document.querySelectorAll('.mySvg'); // 设置图片在靠近视口右侧或底部20%时加载 const rootMargin = '0% 20% 20% 0%'; // 方案1: // 视口底部触发正常 // 视口右侧触发失效:图片刚接触视口右侧即加载(未按20%设置触发) createObserver(svgs, rootMargin, null); // 方案2:(效果相反) // 视口底部触发失效:页面加载时所有图片已加载 // 视口右侧触发正常 // const scrollContainers = document.querySelectorAll('.scroll-container'); // for (const scrollContainer of scrollContainers) { // createObserver(svgs, rootMargin, scrollContainer); // } }, []) return ( <> <div style={{marginBottom: '50px'}}>Awesome Coffee Shops:</div> {coffeeShops.map(shop => { return ( <> <div className='scroll-container'> {shop.photos.map(photo => { return ( <svg width='4032' height='3024' className='mySvg'> <rect x="0" y="0" width='4032' height="3024" stroke='black' fill='white' /> </svg> ); })} </div> <div>{shop.title}</div> </> ); })} </> ); }; export const createObserver = (svgs, rootMargin, root) => { const config = { root, rootMargin, threshold: 0 }; const lazyImageObserver = new IntersectionObserver(function (entries, observer) { entries.forEach(function (entry) { if (entry.isIntersecting) { const svg = entry.target; setTimeout(() => svg.childNodes[0].setAttribute('fill', 'purple'), 500); // 模拟图片下载延迟 observer.unobserve(svg); } }); }, config); svgs.forEach(function (svg) { lazyImageObserver.observe(svg); }); };
CSS
.scroll-container { overflow: auto; white-space: nowrap; } svg { width: 90%; height: 90%; }
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

