使用jQuery同步滚动?

我正在尝试使用以下代码实现两个DIV同步滚动。

DEMO

 $(document).ready(function() { $("#div1").scroll(function () { $("#div2").scrollTop($("#div1").scrollTop()); }); $("#div2").scroll(function () { $("#div1").scrollTop($("#div2").scrollTop()); }); }); 

#div1#div2具有相同的内容但是大小不同

 #div1 { height : 800px; width: 600px; } #div1 { height : 400px; width: 200px; } 

使用此代码,我面临两个问题。

1)滚动没有很好地同步,因为div具有不同的大小。 我知道,这是因为,我直接设置了scrollTop值。 我需要找到滚动内容的百分比,并为另一个div计算相应的scrollTop值。 我不确定,如何找到实际高度和当前滚动位置。

2)此问题仅在firefox找到。 在Firefox中,滚动不像其他浏览器那样流畅。 我认为这是因为上面的代码创建了一个无限循环的滚动事件。 我不确定,为什么这只发生在firefox上。 有没有办法找到滚动事件的来源,以便我可以解决这个问题。

任何帮助将不胜感激。

您可以使用element.scrollTop / (element.scrollHeight - element.offsetHeight)来获取百分比(它将是介于01之间的值)。 因此,您可以将其他元素(.scrollHeight - .offsetHeight)乘以此值进行比例滚动。

为了避免在循环中触发侦听器,您可以暂时取消绑定侦听器,设置scrollTop并再次重新绑定。

 var $divs = $('#div1, #div2'); var sync = function(e){ var $other = $divs.not(this).off('scroll'), other = $other.get(0); var percentage = this.scrollTop / (this.scrollHeight - this.offsetHeight); other.scrollTop = percentage * (other.scrollHeight - other.offsetHeight); // Firefox workaround. Rebinding without delay isn't enough. setTimeout( function(){ $other.on('scroll', sync ); },10); } $divs.on( 'scroll', sync); 

http://jsfiddle.net/b75KZ/5/

这就是我正在使用的。 只需使用要同步的两个元素调用syncScroll(...)函数即可。 我发现pawel的解决方案在鼠标或触控板实际完成操作后继续慢慢滚动存在问题。

请参阅此处的工作示例

 // Sync up our elements. syncScroll($('.scroll-elem-1'), $('.scroll-elem-2')); /*** * Synchronize Scroll * Synchronizes the vertical scrolling of two elements. * The elements can have different content heights. * * @param $el1 {Object} * Native DOM element or jQuery selector. * First element to sync. * @param $el2 {Object} * Native DOM element or jQuery selector. * Second element to sync. */ function syncScroll(el1, el2) { var $el1 = $(el1); var $el2 = $(el2); // Lets us know when a scroll is organic // or forced from the synced element. var forcedScroll = false; // Catch our elements' scroll events and // syncronize the related element. $el1.scroll(function() { performScroll($el1, $el2); }); $el2.scroll(function() { performScroll($el2, $el1); }); // Perform the scroll of the synced element // based on the scrolled element. function performScroll($scrolled, $toScroll) { if (forcedScroll) return (forcedScroll = false); var percent = ($scrolled.scrollTop() / ($scrolled[0].scrollHeight - $scrolled.outerHeight())) * 100; setScrollTopFromPercent($toScroll, percent); } // Scroll to a position in the given // element based on a percent. function setScrollTopFromPercent($el, percent) { var scrollTopPos = (percent / 100) * ($el[0].scrollHeight - $el.outerHeight()); forcedScroll = true; $el.scrollTop(scrollTopPos); } } 

如果div的大小相同,那么下面的代码是一种同步滚动它们的简单方法:

 scroll_all_blocks: function(e) { var scrollLeft = $(e.target)[0].scrollLeft; var len = $('.scroll_class').length; for (var i = 0; i < len; i++) { $('.scroll_class')[i].scrollLeft = scrollLeft; } } 

这里我使用水平滚动,但你可以在这里使用scrollTop。 此函数调用div上的scroll事件,因此e将可以访问事件对象。 其次,你可以简单地计算出在这一行中应用的div的相应大小的比率$('.scroll_class')[i].scrollLeft = scrollLeft;

像发条一样运行(见DEMO )

 $(document).ready(function(){ var master = "div1"; // this is id div var slave = "div2"; // this is other id div var master_tmp; var slave_tmp; var timer; var sync = function () { if($(this).attr('id') == slave) { master_tmp = master; slave_tmp = slave; master = slave; slave = master_tmp; } $("#" + slave).unbind("scroll"); var percentage = this.scrollTop / (this.scrollHeight - this.offsetHeight); var x = percentage * ($("#" + slave).get(0).scrollHeight - $("#" + slave).get(0).offsetHeight); $("#" + slave).scrollTop(x); if(typeof(timer) !== 'undefind') clearTimeout(timer); timer = setTimeout(function(){ $("#" + slave).scroll(sync) }, 200) } $('#' + master + ', #' + slave).scroll(sync); }); 

我喜欢pawel的干净解决方案,但它缺少我需要的东西,并且有一个奇怪的滚动错误,它继续滚动,我的插件将在多个容器上工作,而不仅仅是两个。

http://www.xtf.dk/2015/12/jquery-plugin-synchronize-scroll.html

示例和演示: http : //trunk.xtf.dk/Project/ScrollSync/

插件: http : //trunk.xtf.dk/Project/ScrollSync/jquery.scrollSync.js

$( ‘滚动’)scrollSync();

如果您不想要按比例滚动,而是在每个字段上滚动相同数量的像素,则可以将更改值添加到您将scroll-event绑定到的字段的当前值。

假设#left是小字段, #right是更大的字段。

 var oldRst = 0; $('#right').on('scroll', function () { l = $('#left'); var lst = l.scrollTop(); var rst = $(this).scrollTop(); l.scrollTop(lst+(rst-oldRst)); // <-- like this oldRst = rst; }); 

https://jsfiddle.net/vuvgc0a8/1/

通过添加更改值,而不仅仅是将其设置为#rightscrollTop() ,您可以在小字段中向上或向下滚动,无论其scrollTop()是否小于更大的字段。 这方面的一个例子是Facebook上的用户页面。

这是我来到这里时所需要的,所以我想我会分享。

pawel解决方案(第一个答案)。

对于使用jQuery的horizzontal同步滚动,这是解决方案:

 var $divs = $('#div1, #div2'); //only 2 divs var sync = function(e){ var $other = $divs.not(this).off('scroll'); var other = $other.get(0); var percentage = this.scrollLeft / (this.scrollWidth - this.offsetWidth); other.scrollLeft = percentage * (other.scrollWidth - other.offsetWidth); setTimeout( function(){ $other.on('scroll', sync ); },10); } $divs.on('scroll', sync); 

的jsfiddle

多个水平同步div的另一个解决方案是这个,但它适用于具有相同宽度的div。

 var $divs = $('#div1, #div2, #div3'); //multiple divs var sync = function (e) { var me = $(this); var $other = $divs.not(me).off('scroll'); $divs.not(me).each(function (index) { $(this).scrollLeft(me.scrollLeft()); }); setTimeout(function () { $other.on('scroll', sync); }, 10); } $divs.on('scroll', sync); 

注意:仅适用于宽度相同的div

的jsfiddle