CSS魔法堂:Transition就這麼好玩

前言

 之前提及前端動畫必須使用JS,而CSS3爲咱們帶來transition和@keyframes,讓咱們能夠以更簡單(聲明式代替命令式)和更高效的方式實現UI狀態間的補間動畫。本文爲近期對Transition的學習總結,歡迎各位拍磚。html

屬性介紹

 首先先咱們簡單粗暴瞭解transition屬性吧!前端

transition: <transition-property> <transition-duration> <transition-timing-function> <transition-delay>;

/* 設置啓用Transition效果的CSS屬性
 * 注意:僅會引起repaint或reflow的屬性可啓用Transition效果
 *       [CSS_animated_properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animated_properties)
 */
<transition-property>: all | none | <property> [,<property>]*

/* 設置過渡動畫持續時間,單位爲s或ms
 */
<transition-duration>: 0s | <time> [, <time>]*

/* 設置過渡動畫的緩動函數
 * cubic-bezier的值從0到1
 * [一個很好用的cubic-bezier配置工具](http://cubic-bezier.com)
 */
<transition-timing-function>: linear|ease|ease-in|ease-out|ease-in-out|cubic-bezier(n,n,n,n)

/* 設置過渡動畫的延時,單位爲s或ms
 */
<transition-delay>: 0s | <time> [, <time>]

 另外咱們能夠一次性爲多個CSS屬性啓動Transition效果ide

transition: width 1s ease .6s,
            color .5s linear,
            background 2s ease-in-out;

觸發方式

 既然Transition是UI狀態間的補間動畫,那麼有且僅有修改UI狀態時才能讓動畫動起來。那麼就有3種方式了:wordpress

  1. 僞類.:link,:visited,:hover,:active:focus
  2. 經過JS修改CSS屬性值
  3. 經過JS修改className值

TransitionEnd事件詳解

TransitionEnd Event函數

el.addEventListener("transitionend"
  , e => 
    {
      const pseudoElement = e.pseudoElement // 觸發動畫的僞類
          , propertyName = e.propertyName   // 發生動畫的CSS屬性
          , elapsedTime = e.elapsedTime     // 動畫的持續時間
      // ..................
    })

注意:每一個啓用TransitionCSS屬性的分別對應獨立的transitionend事件工具

/* 觸發3個transitionend事件 */
transition: width 1s ease .6s,
            color .5s linear,
            background 2s ease-in-out;

Visibility也能transition?

 在可啓用Transition的CSS屬性中,咱們發現到一個很特別的CSS屬性——visibilityvisibility常與display相提並論的屬性,它憑什麼能啓用Transition,而display不行呢?這個我真心不清楚,不過咱們仍是瞭解啓用transition的visibility先吧!
visibility是離散值,0(hidden)表示隱藏,1(visible)表示徹底顯示,非0表示顯示。那麼visibility狀態變化就存在兩個方向的差別了:性能

  1. 隱藏顯示,因爲非0就是顯示,那麼從值從0到1的過程當中,其實是從隱藏直接切換到顯示的狀態,所以並無所謂的變化過程;
  2. 顯示隱藏,從1到0的過程當中,存在一段時間保持在顯示的狀態,而後最後一瞬間切換到隱藏,所以效果上是變化延遲,依然沒有變化過程。

 上述代表啓用transition的visibility並無補間動畫的視覺效果,那麼到底有什麼做用呢?答案就是不影響/輔助其餘CSS屬性的補間動畫。其中最明顯的例子就是輔助opacity屬性實現隱藏顯示的補間動畫。學習

<style>
.form-input{
    display: inline-flex;
    line-height: 2;
    border: solid 1px rgba(0,0,0,0.3);
}
.form-input:hover{
        border: solid 1px rgba(0,0,0,0.4);
}
.form-addon{
    font-style: normal;
    color: #666;
    background: #ddd;
    padding-left: 10px;
    padding-right: 10px;
    border-right: solid 1px rgba(0,0,0,0.3);
}
.form-addon-after{
    border-left: solid 1px rgba(0,0,0,0.3);
    border-right: none 0;
}
.form-control{
    border:none 0;
    outline-color: transparent;
    padding: 5px;
    caret-color: #888;
    font-size: 16px;
}
.tips-host{
    position: relative;
}
.tips{
    cursor: default;
    z-index: 999;
    position: absolute;
    top: 120%;
    font-size: 12px;
    color: #444;
    background: #ccc;
    padding: .5em;
    box-shadow: 2px 2px 10px #999;
    transition: box-shadow .2s,
                       opacity 1s,
                       visibility .8s;
    visibility: hidden;
    opacity: 0;
}
.tips:hover{
    box-shadow: 2px 2px 5px #999;
}
.tips::before{
    content: "";
    border: solid 10px transparent;
    border-bottom: solid 10px #ccc;
    position:  absolute;
    transform: translate(0, -100%);
}
.form-control:focus + .tips{
    visibility: visible;
    opacity: 1;
}
</style>
<div class="form-input tips-host" >
    <i class="form-addon">Amount</i>
    <input class="form-control">
    <div class="tips">
        Starts with alphabet, then anything you would like.
    </div>
</div>

 當opacity:0時,須要元素隱藏了但實際上它仍然位於原來的位置,並且能夠攔截和響應鼠標事件,當出現元素重疊時則會致使底層元素失效。而因爲visibility:hidden時,元素不顯示且不攔截鼠標事件,因此在補間動畫的最後設置visibility:hidden爲不俗的解決辦法。flex

display:none讓transition失效的補救措施

 雖然修改display有可能會引起reflow,但它依然不能啓用Transition,這點真心要問問委員會了。更讓人疑惑的是,它不單不支持啓用Transition,並且當設置display:none時其他CSS屬性的Transition均失效。難到這是讓元素脫離渲染樹的後果??動畫

<style>
.box{
  display: none;
  background: red;
  height: 20px;
}
</style>
<div class="box"></div>
<button id="btn1">Transition has no effect</button>
<button id="btn2">Transition takes effect</button>
<script>
const box = document.querySelector(".box")
    , btn1 = document.querySelector("#btn1")
    , btn2 = document.querySelector("#btn2")
btn1.addEventListener("click", e => {
  box.style.display = "block"
  box.style.background = "blue"
})
btn2.addEventListener("click", e => {
  box.style.display = "block"
  box.offsetWidth              // 強制執行reflow
  box.style.background = "blue"
})
</script>

上面的代碼,當咱們點擊btn1時背景色的transition失效,而點擊btn2則生效,關鍵區別就是經過box.offsetWidth強制執行reflow,讓元素先加入渲染樹進行渲染,而後再修改背景色執行repaint。
那麼咱們能夠獲得的補救措施就是——強制執行reflow,下面的操做都可強制執行reflow(注意:會影響性能哦!)

offsetWidth, offsetHeight, offsetTop, offsetLeft
scrollWidth, scrollHeight, scrollTop, scrollLeft
clientWidth, clientHeight, clientTop, clientLeft
getComputeStyle(), currentStyle()

總結

尊重原創,轉載請註明轉自:https://www.cnblogs.com/fsjohnhuang/p/9143035.html ^_^肥仔John

參考

小tip: transition與visibility https://www.cnblogs.com/surfaces/p/4324044.html

相關文章
相關標籤/搜索