使用 jQuery 同步滚动?

IT技术 javascript jquery css scroll
2021-02-21 09:42:44

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

演示

$(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值的。我需要找到滚动内容的百分比并计算scrollTop其他div. 我不确定,如何找到实际高度和当前滚动位置。

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

任何帮助将不胜感激。

6个回答

您可以使用element.scrollTop / (element.scrollHeight - element.offsetHeight)来获取百分比(它将是0之间的值1)。因此,您可以将其他元素乘以(.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/

是否可以使 div2 水平滚动?
2021-04-20 09:42:44
@RafaSashi肯定,只是改变*Height*Width*Top*Left jsfiddle.net/b75KZ/102(编辑:对不起,我以为你的意思是水平两个,但应一样简单,只是改变scrollLeft基础上scrollTop,反之亦然)
2021-04-29 09:42:44
您还可以使用 jQuery.throttle 插件:github.com/cowboy/jquery-throttle-debounce
2021-05-02 09:42:44
@pawel 谢谢我更多地考虑了类似jsfiddle.net/PvVdq 的问题,换句话说就是调整你对这个问题的回答stackoverflow.com/questions/18333085/...
2021-05-06 09:42:44
我创建了一个版本来解决该错误并增加了跨多个容器滚动的能力,而不仅仅是两个:stackoverflow.com/a/34017855/63467
2021-05-08 09:42:44

这就是我正在使用的。只需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);
  }
}

像发条一样运行(见演示

$(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);

});
即使使用鼠标滚轮也能很好地工作。
2021-04-21 09:42:44

如果 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。此函数是scroll在 div上的事件上调用,因此e将可以访问事件对象。其次,您可以简单地计算在此行中应用的 div 的相应大小的比率$('.scroll_class')[i].scrollLeft = scrollLeft;

我喜欢 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

$('.scrollable').scrollSync();

@Frost 有非 jquery 版本吗?
2021-04-15 09:42:44