解決transition動畫與display衝突的幾種方法

來源:互聯網
上載者:User

標籤:style   blog   http   java   color   io   

如demo(如果沒有顯示,請查看源地址http://jsfiddle.net/ihardcoder/HNduT/2/)所示,基本的效果是在點擊“Translate”按鈕後,藍色地區透明度變為0,然後隱藏display:none;點擊Reset按鈕後,首先顯示藍色地區display:block,然後透明度逐漸恢複至1,代碼如下:

 1 var btn1 = $("#testbtn1"); 2 var btn2 = $("#testbtn2"); 3 var container = $("#container"); 4  5 btn1.on(‘click‘, function(e) { 6     container.css({ 7         "transition": "opacity 1s", 8         "-webkit-transition": "opacity 1s", 9         "-moz-transition": "opacity 1s",10         "-o-transition": "opacity 1s",11         "-ms-transition": "opacity 1s",12         "opacity": "0.1"13          });14     setTimeout(function() {15         container.css("display", "none");16     }, 1000);17 });18 btn2.on(‘click‘, function(e) {19     container.css("display","block");20     container.css("display");21     container.css("opacity","1");22 });

上述代碼中第20行看起來很奇怪,可能會有人疑問這句代碼的作用,事實是,如果沒有這句代碼,在點擊Reset後得到的效果是:藍色地區瞬間顯示出來,並沒有透明度改變的過渡效果。

至於產生這種現象的原因,深層次的機制我也尚未搞明白,暫時理解為CSS3的transition過渡不支援display的改變,直接操作display會破壞transition的動畫,所以在第14行通過setTimeout將opacity的transition動畫與display的操作分隔。

而第20行代碼的目的,我是這樣理解的,瀏覽器的UI線程在處理UI操作時,將多個css屬性的set操作加入在同一個tick中處理(關於瀏覽器處理tick機制,請參考http://www.infoq.com/cn/articles/javascript-high-performance-animation-and-page-rendering?utm_source=infoq&utm_medium=popular_links_homepage),也就是說,如果不插入第20行代碼,第19行和第21行的css屬性set操作將會被同時執行,所以將會得到瞬間顯示出來的效果;第20行代碼其實是css屬性的get操作,我的理解是,如果在兩個css屬性的set操作中間插入get操作,UI線程在處理的時候將會按順序執行,display的操作和opacity的操作在不同的tick中被執行,這樣便的到我們想要的過渡效果。

由於display對transition的破壞作用,還有另外一種方法來hack,沒有錯,就是setTimeout!(這貨完全是js的大殺器!)代碼如下:

1  btn2.on(‘click‘, function(e) {2     container.css("display","block");3     setTimeout(function(){4        container.css("opacity","1");5     },delay);6  });

但是用setTimeout的方法有一個弊端,第5行的delay在不同的瀏覽器(甚至不同版本的相同瀏覽器)中需要設定不同的數值,經本人測試,chrome35和IE10下delay=0即可,Firefox30下delay>=14.

第三種解決方案是通過window.requestAnimationFram來實現,代碼如下:

1 btn2.on(‘click‘, function(e) {2       container.css("display","block");3       requestanimationframe(function(){4          container.css("opacity","1");5       });6    });

requestAnimationFram的作用是將opacity的操作延遲到下一個tick中處理,從而將display的操作分隔開,基本原理與setTimeout相同。

另外,關於display為何會破壞transition動畫,目前本人仍未找到相關資料來證明其內部機制,我的個人理解是,display的操作會觸發瀏覽器的reflow操作,而transition支援的效果只是觸發瀏覽器的repaint操作,回到上面的demo,如果我們通過visibility屬性來控制顯示與隱藏,則不會破壞transition的效果。所以,可以暫時這麼認為:reflow與repaint的混合會破壞transition的動畫效果,至於更深層次的原因嘛,借我借我一雙慧眼吧~

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.