序列图片滚动加载完成后页面滚动不顺畅的技术求助
问题原因
滚动到最后一帧后仍频繁触发无意义的图片重绘,占用浏览器资源,导致后续滚动响应卡顿。原代码中每次滚动事件都会调用requestAnimationFrame更新图片,即使帧索引没有变化,这种重复操作会干扰浏览器的滚动事件处理逻辑。
解决方案
通过记录上一帧索引,仅在帧索引变化时执行更新,减少不必要的重绘,同时限制滚动分数的最大值,避免超出范围的滚动影响计算:
修改后的完整JS代码:
const html = document.documentElement; const canvas = document.getElementById("3d"); const context = canvas.getContext("2d"); const frameCount = 27; const currentFrame = index => ( `https://www.in-visionen.de/Webdesign/Webdesign${index.toString().padStart(4, '0')}.jpg` ) const preloadImages = () => { for (let i = 1; i < frameCount; i++) { const img = new Image(); img.src = currentFrame(i); } }; const img = new Image() img.src = currentFrame(1); canvas.width = 3840; canvas.height = 2160; img.onload = function() { context.drawImage(img, 0, 0); } const updateImage = index => { img.src = currentFrame(index); context.drawImage(img, 0, 0); } // 记录上一次渲染的帧索引 let lastFrameIndex = 1; window.addEventListener('scroll', () => { const scrollTop = html.scrollTop; const maxScrollTop = html.scrollHeight - window.innerHeight; // 限制滚动分数最大为1,避免超出范围后计算无效值 const scrollFraction = Math.min(scrollTop / maxScrollTop, 1); const frameIndex = Math.min( frameCount - 1, Math.ceil(scrollFraction * frameCount) ); const targetFrame = frameIndex + 1; // 仅当帧索引变化时才执行更新操作 if (targetFrame !== lastFrameIndex) { lastFrameIndex = targetFrame; requestAnimationFrame(() => updateImage(targetFrame)) } }); preloadImages()
额外优化(可选)
如果希望仅用页面中特定区域的滚动来控制帧切换(比如.design元素的高度范围),可以进一步限定滚动分数的计算范围,避免整个页面滚动影响:
// 获取控制滚动的容器元素 const scrollContainer = document.querySelector('.design'); // 计算该容器对应的有效滚动高度 const frameMaxScrollTop = scrollContainer.offsetHeight - window.innerHeight; window.addEventListener('scroll', () => { const scrollTop = html.scrollTop; // 基于容器高度计算滚动分数,超出后固定为1 const scrollFraction = Math.min(scrollTop / frameMaxScrollTop, 1); const frameIndex = Math.min( frameCount - 1, Math.ceil(scrollFraction * frameCount) ); const targetFrame = frameIndex + 1; if (targetFrame !== lastFrameIndex) { lastFrameIndex = targetFrame; requestAnimationFrame(() => updateImage(targetFrame)) } });
内容的提问来源于stack exchange,提问作者Ayhan
相关产品推荐
相关产品推荐

