2016-07-14 59 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>

相關問題