強制 Mobile Safari 重繪畫面

作者:   發佈於:  

雖然 iOS5 的 Mobile Safari 上已經可以繪製 fixed position 的元素,不過問題真的很多。

比方說,在 fixed position 的元素經常需要被藏起來再重現時,會用 jQuery 的 show / hide方法,或是手動給 CSS display: block / none 來處理。但實際上在 Mobile Safari 上,如果這個固定位的元素基本上是隱形的,要在在使用者觸發事件後,再由程式中 顯示出目標元素,如果文件捲動位置有變,會發現它沒有出現,或是出現在錯誤的位置,或是 需要再由使用者用手指撥動一點點距離,才會看到它出現。

Mobile Safari 似乎有仔細區分出實際有使用者參與的事件,以及由程式中觸發的事件。後 者(像是 $(window).trigger("resize")$(window).scroll(0,0) 等等)並不一定 會立刻促使畫面被重繪。反之,真由使用者觸發的 scrollresize (iPhone / iPad 轉向)卻很容易使畫面重繪。

不過有時,硬要使用者再多摸一下畫面,可能不是好的操作方式。

也就是說會需要一個能在程式中能有效地重繪畫面的方式。這裡有個十分誇張的方法:

// force repaint to reveal a missing fixed-positioned element.
var original_scroll_top = $("body").scrollTop(); 
$("html,body").stop().animate ({ scrollTop: 0 }, 100, function() {
    $("#fixedStuff").css({"position": "relative"});
    window.scroll(0, original_scroll_top);
    $("#fixedStuff").css({"position": "fixed"});
});

此段程式參考 http://stackoverflow.com/a/9808770/56565 ,看來有不少人 也到碰了這種問題。

基本上是使用 jQuery 的 animate 方法,去上下捲動文件一段夠長的距離,還要把 目標元素("#fixedStuff")的 position 改成 relative 再改回 fixed 。實在 是莫名奇妙。

不用 animate 而只用 css 似乎並沒有很好的效果,原因不明。

如果只要求 Mobile Safari 上下捲 1px 這種極小距離,是不會有效果的。必需要 長到會畫面出現一部份空白為止。倒底實際上至少需要多長,也不清楚。

而不幸的是,這麼做的後果便是畫面會出現閃光。每次在重繪時,便會有如同照相機閃光 燈的效果。雖然顯示位置正確了,但這副作用頂誇張的,似乎也好不到哪裡去。

最後實際上還是回到老路,改用 position: absolute 再手動計算位置效果最好。

結論?在 Mobile Safari 上還是不要用太多 position: fixed 的元素為妙。