试试这个。
在 JS Fiddle 中查看
function scrollingSlider(selector, beginpos, endpos) {
var slide,
timeout = 0;
slide = function () {
var scrollpos;
window.clearTimeout(timeout);
timeout = 0;
scrollpos = $(window).scrollTop();
$(selector).each(function () {
var $this = $(this),
margintarget,
margin = parseInt($this.css('margin-left'), 10),
step;
if (scrollpos <= beginpos) {
margintarget = -1000;
} else if (scrollpos >= endpos) {
margintarget = 0;
} else {
margintarget = Math.round(-1000 * (endpos - scrollpos) / (endpos - beginpos));
}
if (margintarget === margin) {
return; // nothing more to do
}
step = margintarget - margin;
if (Math.abs(step) > 25) {
step = 25 * (step < 0 ? -1 : 1);
}
$this.css('margin-left', margin + step);
if (!timeout && (margin + step) !== margintarget) {
timeout = window.setTimeout(slide, 10);
}
});
};
$(window).on('scroll', slide);
}
$(document).ready(function (){
scrollingSlider('.post-129, .post-169', 100, 300);
});
笔记
要使用该scrollingSlider
函数,请传入一个 jQuery 选择器、开始滑入的滚动顶部位置(以像素为单位)以及应完成滑动的以像素为单位的滚动顶部位置。如果您使用字符串选择器,您将避免在 DOM 元素上创建闭包的潜在问题,该闭包可能会干扰在大量使用场景中释放内存。
定位
另外,我建议不要使用滚动位置来确定何时显示元素,而是更改代码以根据每个元素当前顶部的位置与底部视图的距离进行比较的滚动窗口。这完成了两件事:
- 如果您更改页面以添加或删除内容(从而更改元素的垂直位置),则滚动不会出错。
- 更重要的是,对于任何拥有足以容纳整个页面的大屏幕的人来说,他们甚至都不会看到您的滑入式元素,因为他们没有滚动条!将事物的可见性与滚动条的位置(而不是项目必须进入视口的距离)联系起来是使您的内容完全无法访问的好方法——可能不是您想要的。注意:我当前的屏幕是 2880 像素高,如果我将它旋转到纵向模式,它将是 5120 像素高。这是很多一次可见的网页。容纳这些大屏幕尺寸需要仔细考虑。您可以在页面底部添加某种取决于窗口高度的填充或间距,强制滚动条出现并可用(意味着滚动到底部会导致最低可见项目位于或超出页面顶部而不是底部)。
还有一点:我opacity
完全放弃了。问题是因为在 CSS 中你必须说-1000px
as-1000
没有单位并且被忽略。您唯一可以不使用单位的情况是0
-- 否则,浏览器将如何知道您的意思是像素而不是em
s?。
确实,我没有使用 jQuery 的动画能力。我可能有。与其设置我自己的超时来再次运行该函数,我可以简单地告诉 jQuery 将元素动画到正确的位置,.stop()
首先停止任何未完成的动画。那将是完全有效的。这次我只是这样做了。随意修改。
解释
将滑动的初始触发器设置为scroll
事件。在slide
函数中,对于我们感兴趣的每个元素,根据当前滚动位置计算出我们想要滑动到的目标左边距。将元素向该目标移动不超过 25 个像素。如果尚未达到目标位置,请设置计时器以重复此过程。由于滚动事件不仅可以从根本上改变目标位置,而且可以触发它自己的级联动画,因此取消在slide
函数开始时设置的任何未完成的计时器。
速度注意事项
如果你发现 10 毫秒太频繁并且动画太粗或者 CPU 密集型,提高它以减少函数触发的频率,将最大步长增加一个类似的因子(当前为 25)。如果动画太慢或太快,相应地增加或降低最大步长。
进一步提速思路:
在您的网站中,同时运行的其他代码会阻止在 10 毫秒之前调用幻灯片函数。然后奇怪的事情发生了。
在滑动元素上使用 id 而不是类。
按照建议,将超时更改为 40 毫秒或 100 毫秒,并增加对象移动的最大像素数。
In your targeted usage scenario your two images are locked together, so take out the each
function and just do the operation on both at the same time--this should achieve some significant reduction in execution time.
Last, a usage note: Don't include the script multiple times to animate multiple objects. Instead, just call scrollingSlider
multiple times in the ready
function!
UPDATE
Please see the "Positioning" section above, which has been updated with new and important information about screen sizes.