Javascript 确定捕捉滚动元素';s的快照滚动事件已完成 摘要
我正在使用可滚动元素创建图像库。我正在使用CSS的滚动捕捉功能,它允许我捕捉滚动条中的元素(图像)Javascript 确定捕捉滚动元素';s的快照滚动事件已完成 摘要,javascript,css,animation,easing,scroll-snap,Javascript,Css,Animation,Easing,Scroll Snap,我正在使用可滚动元素创建图像库。我正在使用CSS的滚动捕捉功能,它允许我捕捉滚动条中的元素(图像) function scrollHandler(e) { var atSnappingPoint = e.target.scrollLeft % e.target.offsetWidth === 0; var timeOut = atSnappingPoint ? 0 : 150; //see notes clearTimeout(e.target.scro
function scrollHandler(e) {
var atSnappingPoint = e.target.scrollLeft % e.target.offsetWidth === 0;
var timeOut = atSnappingPoint ? 0 : 150; //see notes
clearTimeout(e.target.scrollTimeout);
e.target.scrollTimeout = setTimeout(function() {
console.log('Scrolling is done!');
}, timeOut);
}
myElement.addEventListener('scroll', scrollHandler);
通过绑定到元素的scroll
事件,我可以在用户滚动元素时应用各种操作(比如预加载、隐藏界面元素等)。其中之一取决于滚动事件,需要在滚动完成时停止。但卷轴抓拍给我带来了一个无法预料但却无法处理的局面
我无法准确确定快照滚动操作是否完成。
我可以在每个滚动上设置一个setTimeout
,它会自动取消并重新设置(有效地消除抖动),如果不重置,最终会被调用。但设置此选项时使用的超时可能意味着您在确定是否完成滚动时“太晚了”
底线:我如何检查滚动是否完成,因为:
scroll snap type
已设置)我终于,明确地,解决了这个脑筋急转弯。这比我原来想象的要简单得多。 (注意:在我的例子中,它适用于水平滚动条;在本例中,将
offsetWidth
更改为offsetHeight
并将scrollLeft
更改为scrollTop
,以适应垂直滚动条。)
崩溃
通过使用滚动元素自身的width(或垂直滚动时的高度),我们可以通过将元素的滚动位置(scrollLeft
在我的情况下)除以其宽度(offsetWidth
)来计算它是否达到了捕捉点,如果这产生了一个整数(意思是:宽度正好与滚动位置“匹配”x倍)它已到达捕捉点。我们使用:
然后,如果达到捕捉点,则将超时设置为0(在滚动完成时应触发的设置超时中使用)。否则,使用常规值(在上面的示例150中,请参阅注释)
这是因为当元素实际到达其捕捉点时,最后一个scroll
事件被触发,我们的处理程序(再次)被触发。将timeOut
调整为0将立即调用我们的超时函数;因此当滚动器“点击”捕捉点时,我们立即知道这一点
笔记
在捕捉点上滚动我还没有实现/考虑到这样一个事实,即可以通过滚动捕捉点来“命中”捕捉点。但这是非常罕见的。我会在找到解决方案后更新答案
像素比率:如果计算出错(1像素的剩余部分等,因此函数无法正确解析),则可能存在一些缩放/框模型问题,从而导致滚动位置和偏移宽度计算的计算出错。
这很可能是由设备的像素比率引起的,因此您可以尝试通过将这些值乘以像素比率来“纠正”这些值(向左滚动和宽度)。
重要提示:事实证明,像素比率不仅指示用户是否具有高dpi屏幕,而且在用户缩放页面时也会发生变化
timeout当滚动尚未达到捕捉点时,使用的任意timeout
为150。这足够长,可以防止在Safari@iOS完成滚动之前触发它(它使用贝塞尔曲线进行滚动捕捉,产生大约120-130ms的非常长的“最后一帧”)并且足够短,当用户在捕捉点之间暂停滚动时,可以产生可接受的结果
滚动填充如果已在滚动元素上设置了滚动填充
,则在确定捕捉点时需要将其考虑在内
剩余像素数:您甚至可以进一步细分,以在到达捕捉点之前计算剩余像素数:
var pxRemain = e.target.scrollLeft % e.target.offsetWidth;
var atSnappingPoint = pxRemain === 0;
但请注意,您需要从元素的宽度中减去该值,具体取决于您滚动的方式。这需要您计算滚动的距离,并检查该距离是负值还是正值。然后它将变为:
var pxRemain = e.target.scrollLeft % e.target.offsetWidth;
pxRemain = (pxRemain === 0) ? 0 : ((distance > 0) ? pxRemain : elementWidth - pxRemain);
var atSnappingPoint = pxRemain === 0;
只会折断
编写此脚本时考虑了两种情况:
元素已捕捉到其捕捉点,或
用户已暂停滚动(或捕捉检测不知何故出错)
如果只需要前者,则不需要超时,只需编写:
function scrollHandler(e) {
if (e.target.scrollLeft % e.target.offsetWidth === 0) {
console.log('Scrolling is done!');
}
}
myElement.addEventListener('scroll', scrollHandler);
function scrollHandler(e) {
if (e.target.scrollLeft % e.target.offsetWidth === 0) {
console.log('Scrolling is done!');
}
}
myElement.addEventListener('scroll', scrollHandler);