jQuery scroll事件仅滚动结束触发 如何实现滚动时实时调整元素尺寸
垂直Cover Flow滚动实时更新解决方案
核心问题根因
你感知到的滚动过程中无法实时触发效果,本质是两个问题共同导致的:
- CSS规则里给
li设置了transition: all .25s,所有属性变化都会延迟250ms执行,这是效果出现偏移的最主要原因 - 原始滚动事件逻辑没有和浏览器渲染节奏对齐,高频滚动触发时容易出现掉帧,进一步放大滞后感受
另外原始代码中使用position().top计算元素位置,相对于父元素定位的计算逻辑容易出现偏差,也会导致尺寸计算不准。
具体修复代码
JavaScript代码优化
用requestAnimationFrame包裹计算逻辑,保证每帧只执行一次更新,既避免掉帧也提升实时性,同时修正位置计算逻辑:
// 增加锁避免同一帧内重复触发计算 let isTicking = false; function updateCoverFlow() { const windowOffset = $(window).scrollTop(); const windowMiddle = $(window).height() / 2; $('li').each(function() { // 改用offset().top获取元素相对于文档的绝对位置,计算更准确 const eleTop = $(this).offset().top; const offset = Math.abs(windowMiddle - eleTop + windowOffset); $(this).text(offset); // 增加宽度最小值避免出现负宽度异常 $(this).css('width', Math.max(100, 700 - offset)); }); isTicking = false; } $(window).scroll(function() { if (!isTicking) { requestAnimationFrame(updateCoverFlow); isTicking = true; } }); // 页面加载完成后先执行一次初始化 $(document).ready(updateCoverFlow);
CSS代码调整
删除li的全局过渡规则,如果需要柔和过渡可以仅给宽度设置极短的过渡时长:
body { margin: 0; padding: 0; } .scroll { position: absolute; display: block; width: 100%; } ul { display: block; list-style: none; margin: 0; padding: 0; } li { display: block; margin: auto; width: 300px; height: 70px; background: yellow; margin-bottom: 20px; /* 可根据需要保留弱过渡,不建议超过0.1s,否则会出现明显滞后 */ /* transition: width 0.08s; */ text-align: center; line-height: 70px; font-size: 50px; } .helper { display: block; position: fixed; width: 100%; top: 50%; left: 0%; background: red; height: 1px; }
HTML代码不需要调整。
效果说明
修改后滚动事件的更新会和浏览器渲染帧完全对齐,不会再出现滚动结束才更新的情况,尺寸计算的偏差也会被消除。
内容的提问来源于stack exchange,提问作者Screenload
相关产品推荐
相关产品推荐

