CSS3 transition介紹

transition從效果上看是一種平滑過渡的動畫,本質上是在線性時間內將屬性從開始值過渡到結束值。例如得到焦點,點擊鼠標等動做致使CSS屬性值的變化是瞬間完成的,感受有點生硬。用transition能夠指定在某時間段內將屬性值平滑過渡,加強用戶體驗。javascript

  • 4個子屬性
  • transition-property
  • transition-duration
  • transition-timing-function
  • transition-delay
  • 觸發過渡的方式
  • transitionend事件
  • 隱式過渡
  • 開關過渡和永久過渡
  • auto過渡

4個子屬性

transition有4個子屬性:transition-property,transition-duration,transition-timing-function,transition-delayphp

transition-property指定須要過渡的CSS屬性。並非全部屬性都能過渡的,只有能數字量化的CSS屬性才能過渡。css

哪些屬於能數字量化的CSS屬性呢?例如:前端

顏色系,如color,background-color,border-color,outline-colorjava

數字系,實在太多了,如width,height,top,right,bottom,left,zoom,opacity,line-height,background-position,word-spacing,font-weight,vertical-align,outline-outset,z-index等。css3

01系,如visibility(0表示隱藏,1表示顯示)瀏覽器

還有更多如漸變,陰影等分類請參照W3C的Animation of property types,不一一列舉了。前端工程師

W3C上還有可過渡屬性一覽表Properties from CSS。一般只要能設數字(包括%百分比)的屬性都能過渡。閉包

除了單個指定屬性外,transition-property還能設爲all,表示全部屬性都將得到過渡效果。函數

transition-duration過渡須要的時間,單位可指定s秒,也可指定ms毫秒。默認值是0,表示馬上變化。

若是設置了多個過渡屬性,但每一個屬性的過渡時間都同樣,你不必爲transition-duration設多個值,只有設一個便可,該值會應用到全部過渡屬性上。

transition-timing-function過渡函數,有lineareaseease-inease-outease-in-outcubic-bezier(n,n,n,n)steps

其實它們都是貝賽爾曲線。以下

 
看貝賽爾曲線就知道了, linear是勻速過渡, ease是先快再慢的節奏, ease-in是加速衝刺的節奏, ease-out是減速到中止的節奏, ease-in-out是先加速後減速的節奏。

 

如今動畫的精度愈來愈高,若是預約義好的這些函數知足不了你的需求,能夠經過cubic-bezier(n,n,n,n)自定義平滑曲線。

從上面的圖形中觀察到,貝塞爾曲線有4個點,左下爲起始點P0座標固定爲(0,0),右上爲終點P3座標固定爲(1,1),中間有兩點P1和P2的座標就是cubic-bezier(n,n,n,n)的參數。

經過4條連起來的直線,生成平滑的曲線。一圖勝千言:

 
 

 
 

 
 

 
 
若是要憑腦子空寫出貝賽爾函數的代碼,可能比較困難。好在不用你本身去計算,能夠到工具網站(如 貝賽爾立方)上自動生成想要效果的代碼。
你也能夠在該站點上,體驗一把 lineareaseease-inease-outease-in-out間的差別。

 

steps能夠把過渡階段分割成等價的幾步。什麼意思呢?一圖勝千言:

 
steps函數有兩個參數,第一個參數是分割的數量,第二個參數可選,是關鍵字 startend,不設的話默認是 end
所以 steps(4, start)等價於 step-start(4)steps(4, end)等價於 step-end(4)。例如 steps(4, end)並不是像貝塞爾曲線那樣平滑過渡,
至關於將過渡過程從頭到尾分紅4步,在每一步瞬間完成過渡。最上面的例子中已經有所展現,很容易理解

 

transition-delay延遲開始過渡的時間,默認值是0,表示不延遲,當即開始過渡動做。單位是s秒或ms毫秒。

w3cschool上沒說的是,該屬性還能設負時間,意思是讓過渡動做從該時間點開始啓動,以前的過渡動做不顯示。

你能夠單獨指定這4個子屬性,也能夠像background等屬性同樣,合併在transition屬性裏指定。

但合併時要注意,由於有transition-duration和transition-delay都是時間,瀏覽器會根據前後順序,將第一個時間認做爲transition-duration,第二個時間認做爲transition-delay。

是分開或者合併指定並沒有標準答案。分開指定可能代碼易讀性高一點。

但當頁面須要適應各瀏覽器時,每一個都要加上-ms-,-moz-等前綴,代碼會變的不少,合併在一塊兒代碼稍微少點。

另外也能夠同時指定多個過渡效果,例如transition: background 1s linear 2s, border-radius 2s ease-in 3s;

觸發過渡的方式

常見的就是僞類觸發:hover,:focus,:active,:checked等。還有例如@media媒體查詢,根據設備大小,橫屏豎屏切換時觸發。

還有如click,keydown等JS事件觸發。頁面加載也能觸發就不一一列舉了。總之過渡的本質是在時間段內平滑過渡屬性值,與怎麼觸發沒有關係。

transitionend事件

transition既然涉及時間,天然就有事件。參照MDN有transitionend事件,顧名思義就是過渡結束時觸發該事件。但該事件比較坑。例如過渡padding時,代碼以下:

#tempDiv { padding: 1px; transition-property: padding; transition-duration: 1s; } #tempDiv:hover { padding: 5px; } function showMessage() { console.log('finished'); //過渡結束時觸發打印log } var element = document.getElementById("tempDiv"); element.addEventListener("transitionend", showMessage, false); 

你能夠代碼貼到瀏覽器裏試試,結果出現4條log。

由於過渡屬性指定的是padding,因此在padding-top,padding-right,padding-bottom,padding-left過渡結束時均觸發了transitionend事件。所以log被打印了4次。

若是上述CSS中將transition-property: padding;改成all,一樣會觸發4次。

除非你改爲transition-property: padding-top;這樣才能只觸發一次,但現實中只過渡一邊的場景很是少,一般都是4邊同時過渡,

所以例如padding,margin,border之類的屬性,用transitionend事件會有屢次捕捉的狀況發生。

隱式過渡

transition過渡時有時會出現一些比較曖昧的情形,好比設成em的屬性,如你所知em是根據font-size來計算的。

相似還有rem,vh,vw等都是根據另外一個屬性的值來計算獲得它的值。

舉個例子padding:2em;,若是font-size被改變了,此時padding的「書面值」不變,仍舊是2em,但「實際值」將會發生變化並觸發transition過渡。這被稱做「隱式過渡」。

多數瀏覽器會實現隱式過渡,但傳聞IE很特別,具體有多特別我也沒試過。沒試過就輕信傳聞好像很不嚴謹,但根據IE過往的口碑,我寧肯信其有…前端工程師都懂的。

開關過渡和永久過渡

開關過渡,顧名思義就是觸發源的事件結束後會恢復到原始狀態。永久過渡就是過渡後不恢復到原始狀態。

上面的例子都是開關過渡,當鼠標hover事件結束後,圖片恢復原始尺寸。但永久過渡的話,鼠標hover事件結束後,圖片仍舊保持放大後的尺寸。

//開關過渡 .transition { transition: all 1s ease-in-out; } .transition:hover { transform: scale(1.5); } //永久過渡 .forever { transition: all 1s ease-in-out 999999s; } .forever:hover { transform: scale(1.5); transition: all 1s ease-in-out; } 

由於回到原始尺寸的transition-duration被設成了一個很大的時間,999999s差很少有12天,理論上你頁面開12天就能看到關閉過渡的效果,但現實等於永久過渡。該技巧無需任何JS腳本。

auto過渡

一般咱們屬性過渡時,都是定值到定值的過渡,例如width:100px過渡到200px。但要過渡到width:auto就不行了。

就算你指定transition: width 1s linear;會發現根本不會有1秒的平滑的過渡效果,而是瞬間完成過渡。

.div1 {
    background-color: red;
    width: 100px;
    height: 50px;
}
#box1:hover {
    width: auto;
    transition: width 1s linear;
}
<div id="box1" class="div1"></div> 

若是想要過渡效果,必須將auto轉換爲固定值。那麼問題來了,如何轉換呢?

須要靠JS,經過getComputedStyle獲取auto後的固定值後,經過style設置該值,而後再觸發CSS的過渡效果。

window.onload = function(){ var box = document.getElementById("box2"), originWidth = box.clientWidth, width2AutoLater = null, width2OriginLater = null; var width2Auto = function(element, time) { if (typeof window.getComputedStyle == "undefined") return; var width = window.getComputedStyle(element).width; element.style.width = "auto"; var targetWidth = window.getComputedStyle(element).width; element.style.width = width; setTimeout(function() { element.style.transition = "width "+ time +"ms linear"; element.style.width = targetWidth; }, 10); }; var width2Origin = function(element, time) { setTimeout(function() { element.style.transition = "width 0s linear"; element.style.width = originWidth + "px"; }, 10); }; function callLater(func, paramA, paramB){ return function(){ func.call(this, paramA, paramB); }; } width2AutoLater = callLater(width2Auto, box, 1000); width2OriginLater = callLater(width2Origin, box, 1000); box.addEventListener("mouseenter", width2AutoLater); box.addEventListener("mouseleave", width2OriginLater); } <div id="box2" class="div1"></div> 

代碼耐心看看應該能看明白。無CSS,全靠JS實現過渡效果。

思路:給div註冊了mouseenter和mouseleave事件來模擬hover效果。

mouseenter綁定width2Auto函數,函數裏臨時將div的width設爲auto後,用getComputedStyle獲得寬度值,將該寬度值和transition設進該div的style裏。

mouseleave綁定width2Origin函數,函數裏將div的width改回初始值。

由於註冊事件的函數addEventListener的第二個參數是回調函數名,不能給回調函數傳參數。

所以,使用閉包的特性,定義了callLater中間函數,函數裏經過call調用上述兩個函數。

相關文章
相關標籤/搜索