2013-11-02 21 views
6

我有一個網頁,通過AJAX注入HTML。我不知道,先驗,內容的大小,但我需要根據其大小定位內容在頁面上。這裏有一個簡單的方法是行不通:如何確定瀏覽器何時完成繪製插入的元素?

  1. 設置父容器的不透明度爲0
  2. 插入內容到DOM。
  3. 測量尺寸,例如$el.outerWidth(true)
  4. 根據這些尺寸定位內容。
  5. 將父容器的不透明度(背面)設置爲1.0。

這種方法的問題是,內容相當複雜,包括圖像。當調用outerWidth()時,瀏覽器尚未完成重新繪製屏幕,​​以致返回的尺寸不準確。 (有趣的是,在我的情況下,初始尺寸總是明顯大於最終值,而不是我想象的那樣)。

我可以通過在第2步和第3步之間設置定時器來減少問題,但無論多長時間我做定時器,肯定會有一些瀏覽器在某些系統上超過它。如果我讓計時器足夠長以覆蓋大多數情況,那麼會通過引入不必要的延遲來懲罰用戶更快的系統。雖然下面提到的幾個答案暗示了setTimeout(fn, 0)就足夠了,但我發現情況並非如此。我在2012年的MacBook Air上測量的塗漆時間高達60毫秒,一個答案低於500毫秒。

它看起來像Mozilla在同一時間有可能已經解決了我的問題...如果它仍然存在一個onPaint event,如果其他瀏覽器都採用了。 (兩者都不是這種情況)。在報告元素更改時,Mutation Observers似乎沒有考慮繪製時間。

非常感謝解決方案或意見。如下所述,這已經被問到過,但大多數問題至少已經過了一年,我已經迫不及待地想再試一次了。


相關問題,這不,不幸的是,提供了一個可行的答案


更新:嗯,看來我們確實沒有針對此問題的通用解決方案。在我的具體情況中,我發現一旦內容被加載並且佈局完成,就會可靠地更改屬性。 JavaScript調查此屬性的更改。一點都不優雅,但這是我能找到的最佳選擇。

+0

怎麼樣將它添加到與'顯示的DOM:none',推遲執行(以'setTimeout')和然後根據其高度/寬度來安排事物? –

+0

圖像下載完成後,是否應該啓動'load'事件?並且不是一旦檢索到的圖像的尺寸?在將其包含在需要它的位置之前,可能會在視口之外渲染圖像,以確保瀏覽器實際計算尺寸(同時考慮CSS規則)。由於onload事件在重新繪製完成之前觸發,因此 – Kiruse

回答

-1

你可以看到,如果窗口負荷會做的伎倆。我不知道它是否觸發不止一次,當新的內容加載時,或不。

但對於圖像,你可以使用這樣的東西。

//調用函數匹配的圖像加載完成後

function imagesLoadedEvent(selector, callback) { 
    var This = this; 
    this.images = $(selector); 
    this.nrImagesToLoad = this.images.length; 
    this.nrImagesLoaded = 0; 

    //check if images have already been cached and loaded 
    $.each(this.images, function (key, img) { 
     if (img.complete) { 
      This.nrImagesLoaded++; 
     } 
     if (This.nrImagesToLoad == This.nrImagesLoaded) { 
      callback(This.images); 
     } 
    }); 

    this.images.load(function (evt) { 
     This.nrImagesLoaded++; 
     if (This.nrImagesToLoad == This.nrImagesLoaded) { 
      callback(This.images); 
     } 
    }); 
} 

$("#btn").click(function() { 
    var c = $("#container"), evt; 
    c.empty(); 
    c.append("<img src='" + $("#img1").val() + "' width=94>"); 
    c.append("<img src='" + $("#img2").val() + "' width=94>"); 
    c.append("<img src='" + $("#img3").val() + "' width=94>"); 
    evt = new imagesLoadedEvent("img", allImagesLoaded); 
}); 

function allImagesLoaded(imgs) { 
    //this is called when all images are loaded 
    //console.log("all " + imgs.length + " images loaded"); 
} 

js fiddle for images loaded

+0

onload將不起作用。另外,在我的情況下,內容是標記(可能包括或不包括圖像),而不是圖像。 –

+0

如果它不包含圖像,那麼您可以在每個標記塊的最後添加一個透明/隱藏/ 1px * 1px圖像,以便它將添加的最後一個東西,以及image.load事件將在everyhing已完成加載。 –

+0

如上所述,卸載將不起作用,因爲卸載事件在重新繪製完成之前觸發。 (另外,在這種情況下,我無法控制內容) –

相關問題