Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/386.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用jQuery同步滚动?_Javascript_Jquery_Css_Scroll - Fatal编程技术网

Javascript 使用jQuery同步滚动?

Javascript 使用jQuery同步滚动?,javascript,jquery,css,scroll,Javascript,Jquery,Css,Scroll,我试图用下面的代码实现两个DIV的同步滚动 比如说,#div1和#div2的内容非常相同,但大小不同 #div1 { height : 800px; width: 600px; } #div1 { height : 400px; width: 200px; } 有了这段代码,我面临两个问题 1) 滚动没有很好地同步,因为div的大小不同。我知道,这是因为我直接设置了scrollTop值。我需要找到滚动内容的百分比,并为另一个div计算相应的scrollTop值。我不知道,如何找到实际

我试图用下面的代码实现两个
DIV
的同步滚动

比如说,
#div1
#div2
的内容非常相同,但大小不同

#div1 {
 height : 800px;
 width: 600px;
}
#div1 {
 height : 400px;
 width: 200px;
}
有了这段代码,我面临两个问题

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

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


任何帮助都将不胜感激。

您可以使用
element.scrollTop/(element.scrollHeight-element.offsetHeight)
获取百分比(该值介于
0
1
之间)。因此,您可以将另一个元素的
(.scrollHeight-.offsetHeight)
乘以此值,以便按比例滚动

为了避免触发循环中的侦听器,您可以暂时解除侦听器的绑定,设置
滚动条
,然后重新绑定

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

如果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;
        }

    }
滚动所有块:功能(e){
var scrollLeft=$(e.target)[0];
变量len=$('.scroll_class')。长度;
对于(变量i=0;i
这里我使用水平滚动,但你可以在这里使用滚动顶。此函数在div上的
scroll
事件上调用,因此
e
将有权访问事件对象。
其次,您可以简单地计算div的相应大小的比率,以应用于此行
$('.scroll_class')[i]

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

参见工作示例

像钟表一样运转(请参阅)


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

对于使用jQuery的水平同步滚动,以下是解决方案:

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

另一种用于多个水平同步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);
NB:仅适用于宽度相同的div


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

示例和演示:

插件:

$('.scrollable').scrollSync()


如果不希望按比例滚动,而是希望在每个字段上滚动等量的像素,可以将更改值添加到要绑定滚动事件的字段的当前值

假设
#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;
});
var oldRst=0;
$('#right')。在('scroll',函数(){
l=$('左');
var lst=l.scrollTop();
var rst=$(this.scrollTop();

l、 scrollTop(lst+(rst oldst));//我通过将滚动百分比设置为定点表示法解决了同步滚动循环问题:
percent.toFixed(0)
,参数为0。这可以防止两个同步元素之间的分数滚动高度不匹配,这两个元素一直试图“追赶”这段代码最多只需要一个额外的步骤(即,用户停止滚动后,第二个元素可能会继续滚动一个额外的像素)就可以让他们赶上。这不是一个完美的解决方案,也不是最复杂的,但肯定是我能找到的最简单的解决方案

var left = document.getElementById('left');
var right = document.getElementById('right');
var el2;
var percentage = function(el) { return (el.scrollTop / (el.scrollHeight - el.offsetHeight)) };

function syncScroll(el1) {
  el1.getAttribute('id') === 'left' ? el2 = right : el2 = left;
  el2.scrollTo( 0, (percentage(el1) * (el2.scrollHeight - el2.offsetHeight)).toFixed(0) ); // toFixed(0) prevents scrolling feedback loop
}

document.getElementById('left').addEventListener('scroll',function() {
  syncScroll(this);
});
document.getElementById('right').addEventListener('scroll',function() {
  syncScroll(this);
});


你也可以使用jQuery.throttle插件:可以让div2水平滚动吗?@RafaSashi当然,只需将
*高度
更改为
*宽度
,将
*顶部
更改为
*左侧
(编辑:对不起,我以为你指的是水平方向和水平方向,但应该同样简单,只要根据
scrollTop
更改
scrollLeft
,反之亦然)@pawel谢谢,我更多地考虑了类似的问题,换句话说,根据您对这个问题的回答,我创建了一个版本,该版本解决了这个问题,并增加了在多个容器上滚动的能力,而不仅仅是两个:有点类似的问题和我的答案:@Frost有没有非jquery版本?即使使用mousewheel,效果也很好。
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);
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;
});
var left = document.getElementById('left');
var right = document.getElementById('right');
var el2;
var percentage = function(el) { return (el.scrollTop / (el.scrollHeight - el.offsetHeight)) };

function syncScroll(el1) {
  el1.getAttribute('id') === 'left' ? el2 = right : el2 = left;
  el2.scrollTo( 0, (percentage(el1) * (el2.scrollHeight - el2.offsetHeight)).toFixed(0) ); // toFixed(0) prevents scrolling feedback loop
}

document.getElementById('left').addEventListener('scroll',function() {
  syncScroll(this);
});
document.getElementById('right').addEventListener('scroll',function() {
  syncScroll(this);
});