2016-07-14 54 views
8

在我的页面中,我有两个宽度相同的表格,它们都是水平滚动的。当每个滚动时,我需要将两个表都设置为相同的位置。如何使用defineSetter在两个对象中正确设置scrollLeft?

其实,我的代码是:

var scrollA = $('#scrollA'), 
    scrollB = $('#scrollB'); 

scrollA.on('scroll', function() { 
    scrollB[0].scrollLeft = scrollA[0].scrollLeft; 
}); 

它的工作原理。问题是,有些情况下加载的数据足够大,从而减慢浏览器和滚动事件的速度。

然后,我试图改善这些情况下的用户体验。


我做了这个片段,我尝试使用的Object__defineSetter__功能:

var elementA = { scrollLeft: 30 }, 
 
    elementB = { scrollLeft: 30 }; 
 

 
elementA.__defineSetter__('scrollLeft', val => elementB.scrollLeft = val); 
 

 
elementA.scrollLeft += 5; 
 
console.log(elementA.scrollLeft + ' == ' + elementB.scrollLeft);

但是你可以看到正在运行的代码段,它设置undefinedelementA.scrollLeftNaNelementB.scrollLeft

我想在这里得到一些指导,谢谢你的时间。

+0

'__defineSetter__是'已过时,使用'defineProperty()' – zer00ne

+0

而不必单独的滚动条为每个表为什么不能ü尝试把他们都在一个容器中,有一个的滚动条到该容器,以便我们可以避免这种情况。我建议这个bcoz你说这两个表具有相同的宽度 – Varatharaj

+0

@Varatharaj。实际上,它是我正在处理的一个插件,它冻结了表格的列和/或标题...我现在无法测试它,但我会稍后尝试您的想法 –

回答

2

滚动事件可以以高速率触发,因此您可以通过调节滚动事件处理程序来获得更平滑的滚动,正如trincot在其答案中所述。您可以使用setTimeout来调节功能。当在屏幕上移动东西或处理其他可见效果时,我更喜欢requestAnimationFrame

​​在下一次重绘之前运行回调,因此浏览器可以进行一些优化。

此代码将让你更接近的解决方案,它是基于this example from MDN

var scrollA = $('#scrollA'), 
    scrollB = $('#scrollB'), 
    running = false; 

scrollA.on('scroll', function() { 
    // if we already requested an animation frame, do nothing 
    if (!running) { 
    window.requestAnimationFrame(function() { 
     // synchronize table B and table A 
     scrollB[0].scrollLeft = scrollA[0].scrollLeft 
     // we're done here and can request a new frame 
     running = false; 
    }); 
    } 

    running = true; 
}); 

您可以使用传递给回调的时间戳进一步抖同步,但你可以用有点呆滞结束如果放置太多延迟,请在第二个表格中滚动。

2

您对__defineSetter__调用替换财产scrollLeft一个具有相同的名称,这意味着你不能得到原来的财产了。一旦你叫__defineSetter__,在undefined物业结果中的任何阅读:

console.log(scrollA[0].scrollLeft); // some number, like 10 
scrollA[0].__defineSetter__('scrollLeft', val => scrollB[0].scrollLeft = val) 
console.log(scrollA[0].scrollLeft); // undefined 

此外,浏览器并没有通过分配改变scrollLeft值,你会在JavaScript这样做,所以setter函数不会在滚动事件期间被调用。您可以通过将一个console.log在setter函数验证这一点:当您滚动什么也不显示:

scrollA[0].__defineSetter__('scrollLeft', val => console.log(val)) 

对于上述两个原因是没有希望的,你可以捕捉使用__defineSetter__滚动变化。您需要先听听scroll事件。

,如果你做同步异步你可能会取得更好的成绩,并跳过一些更新的,当你有发生的许多滚动事件:

var scrollA = $('#scrollA'), 
    scrollB = $('#scrollB'), 
    tmr = -1; 

scrollA.on('scroll', function() { 
    clearTimeout(tmr); 
    tmr = setTimeout(_ => scrollB[0].scrollLeft = scrollA[0].scrollLeft, 0); 
}); 

现在,当浏览器立即产生一个以上的滚动情况下,第二个将预先清空您的预定更新scrollB[0].scrollLeftclearTimeout将阻止该更新发生,并且下一个将被调度。

你可以用setTimeout延迟参数发挥找到正确的平衡:

增加延迟将防止叠加起来的事件,然后使scrollB会更敏感的方式同步,但很少更新将被制作为scrollB的scrollLeft属性,这可以使其滚动不那么流利。

+0

不幸的是'clearTimeout'不同步两个卷轴。我认为它更像一个'scroll-end'事件。 –

+0

使用'clearTimeout'不是为了同步,而是为了清空超时队列。它不会结束滚动,它由它正在响应的滚动事件驱动,并被'setTimeout'处理。如果你看到问题,你能用小提琴演示吗? – trincot

+1

@Guedes尝试使用'requestAnimationFrame',参见MDN中的[this example](https://developer.mozilla.org/en/docs/Web/Events/scroll#Example)。我认为不可能获得完美的同步,至少在低端设备 – jbmartinez

0

不要这样做。把它做成一张桌子。把事情简单化。看例子。

<!DOCTYPE html> 
 
<html> 
 
<head> 
 
<style> 
 
table { 
 
    font-family: arial, sans-serif; 
 
    border-collapse: collapse; 
 
    width: 2000px; 
 
} 
 

 
td, th { 
 
    border: 1px solid #dddddd; 
 
    text-align: left; 
 
    padding: 8px; 
 
} 
 

 
tr:nth-child(even) { 
 
    background-color: #dddddd; 
 
} 
 
</style> 
 
</head> 
 
<body> 
 

 
<table> 
 
    <tr> 
 
    <th>Company</th> 
 
    <th>Contact</th> 
 
    <th>Country</th> 
 
    </tr> 
 
    <tr> 
 
    <td>Alfreds Futterkiste</td> 
 
    <td>Maria Anders</td> 
 
    <td>Germany</td> 
 
    </tr> 
 
    <tr> 
 
    <td>Centro comercial Moctezuma</td> 
 
    <td>Francisco Chang</td> 
 
    <td>Mexico</td> 
 
    </tr> 
 
    <tr> 
 
    <th>Ernst Handel</th> 
 
    <th>Roland Mendel</th> 
 
    <th>Austria</th> 
 
    </tr> 
 
    <tr> 
 
    <td>Island Trading</td> 
 
    <td>Helen Bennett</td> 
 
    <td>UK</td> 
 
    </tr> 
 
    <tr> 
 
    <td>Laughing Bacchus Winecellars</td> 
 
    <td>Yoshi Tannamuri</td> 
 
    <td>Canada</td> 
 
    </tr> 
 
    <tr> 
 
    <td>Magazzini Alimentari Riuniti</td> 
 
    <td>Giovanni Rovelli</td> 
 
    <td>Italy</td> 
 
    </tr> 
 
</table> 
 

 
</body> 
 
</html>

相关问题