滚动多个元素/DIV

3

我希望同时滚动多个div。

目前有一种方法可以实现,但是在性能较差的设备上(尤其是移动设备)表现不佳。

<!-- HTML -->
<div class="container">
    <div class="row">
        <div class="scroller">
            <div>some really long content that just keeps going on and on and on and on and on and on and on and on and on and on and on and on and on</div>
        </div>
    </div>
    <div class="row">
        <div class="scroller">
            <div>some really long content that just keeps going on and on and on and on and on and on and on and on and on and on and on and on and on</div>
        </div>
    </div>
    <div class="row">
        <div class="scroller">
            <div>some really long content that just keeps going on and on and on and on and on and on and on and on and on and on and on and on and on</div>
        </div>
    </div>
    <div class="row">
        <div class="scroller">
            <div>some really long content that just keeps going on and on and on and on and on and on and on and on and on and on and on and on and on</div>
        </div>
    </div>
    <div class="row">
        <div class="scroller">
            <div>some really long content that just keeps going on and on and on and on and on and on and on and on and on and on and on and on and on</div>
        </div>
    </div>
</div>
<style>
/* CSS */
    .container { width:300px; }
    .scroller { width:100%; height:40px; padding:0 0 16px; line-height:40px; overflow-x:auto; overflow-y:hidden; white-space:nowrap; }
</style>

<script>
// jQuery
$(".scroller").scroll(function(){
    $(".scroller").scrollLeft($(this).scrollLeft());
});
</script>

这是一个笔/demo

我发现当我滚动一个元素时,它会滚动相同类别的其他元素,但由于我在该类别上设置了一个滚动“监听器”,因此对于每个已使用scrollLeft方法滚动的其他元素,函数会再次触发。

有人有任何想法如何改进这个问题吗?


所以,只是为了澄清一下:滚动条同时滚动的行为是有意的,只是为了提高性能? - Markai
没错,@Markai。 - RussAtkins
它们是否应该实时更新,即当滚动条移动时,还是在滚动结束时移动它们就足够了? - Markai
生产环境非常理想,接口的想法是实时比较两行数据/文本。 - RussAtkins
4个回答

2
您可以使用以下代码片段:{需要一些测试,不确定它是否处理所有情况}
$(".scroller").css('outline', 0).attr('tabindex' , -1).scroll(function(e){
    if (!$(this).is(':hover') && !$(this).is(':focus'))  return;
    $(".scroller").not(this).scrollLeft($(this).scrollLeft());
});

这绝对快了很多,谢谢。但是在移动设备(Android - Chrome)上,似乎需要“touchstart”并等待几毫秒才能应用:focus或:hover。可以通过将.scroller:hover,.scroller:focus {background-color:#333;}添加到CSS中来演示此问题。 - RussAtkins

1
在调用scrollLeft()之前,您可以禁用所有元素的滚动处理程序,然后重新启用滚动处理程序。这样可以防止处理程序被重复调用。
var scrollHandler = function(){
  var $scrollers = $(".scroller");
  $scrollers.off("scroll", scrollHandler);
  $scrollers.scrollLeft($(this).scrollLeft());
  setTimeout(function(){$scrollers.on("scroll", scrollHandler);}, 0);
}

$(".scroller").on("scroll", scrollHandler);

1
依我的看法,你应该延迟重新绑定事件: setTimeout(function(){$scrollers.on("scroll", scrollHandler);}, 0); - A. Wolff
我想这是最简洁的方式! - A. Wolff
看起来这在我的手机上性能相当,不幸的是。不过想法不错! - RussAtkins

1

你能否只滚动那些滚动位置不同的元素?

$(".scroller").on('scroll', function(event){
  var a = $(this).scrollLeft();
  $(".scroller").each(function(){
    var b = $(this).scrollLeft();
    if(a !== b){
      $(this).scrollLeft(a);
    }
  });
});

1
不幸的是,仍会触发其他 DIV 的滚动事件。尽管我不确定 OP 问题的确切问题是什么。 - A. Wolff

0
我认为最大的问题是,你在事件侦听器中触发了附加事件侦听器的元素的滚动事件。如果将其排除在要滚动的元素之外,则应在低性能硬件上获得更大的性能提升:
$(".scroller").scroll(function(e){
    $(".scroller").not(this).scrollLeft($(this).scrollLeft());
});

我最初尝试了这个,问题是"$(this).scrollLeft()"会重新运行另一个".scroller"上的整个方法,而这反过来又会调用它们自己...可以通过将以下内容添加到滚动方法中来显示这一点: var $index = $(this).index(".scroller"); // 这是要忽略的索引。 console.log($index); - RussAtkins

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接