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