簡體   English   中英

當元素快速調整大小時,JavaScript的offsetWidth和offsetHeight給出錯誤的值

[英]JavaScript's offsetWidth and offsetHeight give wrong value when element is resizing quickly

我正在使用香草javascript創建自己的滾動條組件。 該元素是可調整大小的,因此在調整其大小時,滾動條的最大滾動位置和大小將隨之變化。

如果我以正常速度調整大小,一切都很好,但是如果我快速測試,計算結果(大小和最大位置)會產生錯誤的結果,我猜是因為offsetWidthoffsetHeight錯誤。

我的滾動條的渲染功能在調整大小時觸發,sbv表示滾動條為垂直,sbh表示滾動條為水平

this.sbv.size = this.content.offsetHeight / this.content.scrollHeight;
this.sbv.style.height = (this.sbv.size * 100) + "%";
this.sbv.max = (100 - this.sbv.size * 100) / 100 * this.content.offsetHeight;
this.sbv.pos = this.content.scrollTop / this.content.scrollHeight * this.content.offsetHeight;
this.sbv.style.top = (this.sbv.pos / this.content.offsetHeight * 100) + "%";

this.sbh.size = this.content.offsetWidth / this.content.scrollWidth;
this.sbh.style.width = (this.sbh.size * 100) + "%";
this.sbh.max = (100 - this.sbh.size * 100) / 100 * this.content.offsetWidth;
this.sbh.pos = this.content.scrollLeft / this.content.scrollWidth * this.content.offsetWidth;
this.sbh.style.left = (this.sbh.pos / this.content.offsetWidth * 100) + "%";

有人知道為什么會這樣嗎? TIA

那只是一個理論上的答案,因為我沒有花時間來設置一個repro案例,並且因為“ 產生錯誤的結果 ”的描述有點寬泛。


我懷疑問題實際上與您的主張相反: offsetWidthoffsetHeightscrollHeightscrollWidth實際上給您正確的值,這意味着您可能沒有想到。

為了返回正確的值,這些屬性的確觸發了文檔中元素的所有邊界框的重新計算,這稱為“重排”
此重排意味着您先前設置的所有CSS規則現在都已應用並處於活動狀態。

所以在您的代碼中,當您執行

elem.size = content.offsetHeight / content.scrollHeight;
elem.style.height = (elem.size * 100) + "%";
elem.max = (100 - elem.size * 100) / 100 * content.offsetHeight;

第一行中content.offsetHeight的值與第三行中的content.offsetHeight的值可能不再相同。

 var elem = document.getElementById('elem'); var content = document.getElementById('content'); console.log('before', content.offsetHeight); elem.size = content.offsetHeight / content.scrollHeight; elem.style.height = (elem.size * 100) + "%"; elem.max = (100 - elem.size * 100) / 100 * content.offsetHeight; console.log('after', content.offsetHeight); 
 body{ height: 100vh; } #content,#elem { border: 1px solid; } #elem { height: 800px; } 
 <div id="content"> <div id="elem"></div> </div> 

因此,不僅觸發這樣的多次重排對於性能來說是可怕的,而且您的計算確實可能會出錯。

最好的辦法是在傳遞變量之前先緩存所有當前值,進行所有計算,最后才設置所有新樣式。

還要注意,所有這些都最好在requestAnimationFrame去抖動器中運行,因此每個繪畫幀僅發生一次。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM