1. 程式人生 > >CSS動畫實戰:建立一個太極Loading圖

CSS動畫實戰:建立一個太極Loading圖

這裡主要是使用CSS的animation和偽類來構建,分析設定關鍵幀的執行順序和時間段。

效果

動畫分析

首先通過效果對動畫執行進行一下分析:

  1. 邊框的四條邊進行按順序動畫載入 。
  2. 矩形邊框變為圓行邊框。
  3. 太極圖內部圖案漸漸出現。
  4. 太極圖旋轉。
  5. 整個動畫逆序執行。

針對上面的1效果是需要思考一下的,其他都比較容易實現。5效果只需設定屬性animation-direction: alternate即可,整體動畫加入animation-iteration-count: infinite來保證無限迴圈。

靜態效果實現

首先將靜態效果做出來。

html結構:

<div id="loader">
  <div class="logo">
    <div class="left"></div>
    <div class="right"></div>
  </div> 
  <p>Loading...</p>
</div>

CSS(LESS)部分:

@border-width:2px;
@loader-width:150px;
@loader-insider-width:@loader-width * 0.15
;
@animate-time:4s; *{ margin: 0; padding: 0; border: 0; } html, body{ width: 100%; height: 100%; } #loader{ position: absolute; top: 0; left: 0; bottom: 0; right: 0; display: flex; flex-direction: column; justify-content: center; align-items: center; p { padding: 1.5em; font-family
: Arial; } .logo{ width: @loader-width; height: @loader-width; position: relative; &:before{ position: absolute; content: ''; left: 0; top: 0; border-color: transparent; border-width: @border-width; border-style: solid; border-top-color: #000; border-right-color: #000; width: 100%; height: 100%; } &:after{ position: absolute; content: ''; bottom: -2 * @border-width; right: -2 * @border-width; border-color: transparent; border-width: @border-width; border-style: solid; border-bottom-color: #000; border-left-color: #000; width: 100%; height: 100%; } .left{ position: absolute; width: 50%; height: 100%; top: @border-width; right: 50%; background-color: #000; border-top-left-radius: 100% 50%; border-bottom-left-radius: 100% 50%; &:before{ position: absolute; content: ''; width: 100%; height: 50%; bottom: 0; left: 50%; border-radius: 50%; background-color: #000; } &:after{ position: absolute; content: ''; width: @loader-insider-width; height: @loader-insider-width; background-color: #fff; bottom: ~'calc(25% - @{loader-insider-width} / 2)'; left: ~'calc(100% - @{loader-insider-width} / 2)'; border-radius: 50%; } } .right{ position: absolute; width: 50%; height: 100%; top: @border-width; left: 50%; border-top-right-radius: 100% 50%; border-bottom-right-radius: 100% 50%; &:before{ position: absolute; content: ''; width: 100%; height: 50%; top: 0; right: 50%; border-radius: 50%; background-color: #fff; } &:after{ position: absolute; content: ''; width: @loader-insider-width; height: @loader-insider-width; background-color: #000; top: ~'calc(25% - @{loader-insider-width} / 2)'; right: ~'calc(100% - @{loader-insider-width} / 2)'; border-radius: 50%; } } } }

效果:

動畫實現

上面已經把靜態的效果實現了,現在將動畫部分抽離出來。

動畫關鍵幀時間段

根據效果,做如下時間段劃分:

邊框效果實現

.logo的兩個偽類的寬高設定為0,然後新增動畫效果:

.logo{
    width: @loader-width;
    height: @loader-width;
    position: relative;
    animation: spin @animate-time infinite;
    animation-direction: alternate;
    animation-timing-function:ease;

    &:before{
      position: absolute;
      content: '';
      left: 0;
      top: 0;
      border-color: transparent;
      border-width: @border-width;
      border-style: solid;
      animation: line-before @animate-time infinite;
      animation-direction: alternate;
    }

    &:after{
      position: absolute;
      content: '';
      bottom: -2 * @border-width;
      right: -2 * @border-width;
      border-color: transparent;
      border-width: @border-width;
      border-style: solid;
      animation: line-after @animate-time infinite;
      animation-direction: alternate;
    }
}

keyframes:

@keyframes line-before {
  0% {
    width: 0;
    height: 0;
    border-top-color: #000;
  }

  9.9% {
    border-right-color: transparent;
  }

  10% {
    width: 100%;
    border-right-color: #000;
    border-top-color: #000;
    height: 0;
  }

  20%,100% {
    width: 100%;
    border-right-color: #000;
    border-top-color: #000;
    height: 100%;
  }

  40% {
    width: 100%;
    border-right-color: #000;
    border-top-color: #000;
    height: 100%;
    border-radius: 0;
  }

  //在執行到50%的時候變圓
  50%, 100% {
    width: 100%;
    border-right-color: #000;
    border-top-color: #000;
    height: 100%;
    border-radius: 50%;
  }
}

@keyframes line-after {
  0%,19.9% {
    border-color: transparent;
    width: 0;
    height: 0;
  }
  20% {
    width: 0;
    height: 0;
    border-bottom-color: #000;
  }

  29.9% {
    border-left-color: transparent;
  }

  30% {
    width: 100%;
    border-left-color: #000;
    border-bottom-color: #000;
    height: 0;
  }

  40% {
    width: 100%;
    border-left-color: #000;
    border-bottom-color: #000;
    height: 100%;
    border-radius: 0;
  }

  //在執行到50%的時候變圓
  50%, 100% {
    border-radius: 50%;
    width: 100%;
    border-left-color: #000;
    border-bottom-color: #000;
    height: 100%;
  }
}

內部圖案出現效果

這個直接調一下透明度即可:

@keyframes left-right-fade {
  0%, 50%{
    opacity: 0;
  }

  75%, 100% {
    opacity: 1;
  }
}

旋轉效果

@keyframes spin {
  0%, 75%{
    transform:rotate(0deg);
  }

  90%, 100% {
    transform:rotate(360deg);
  }
}

所有樣式程式碼

//author: 王樂平
//date: 2017.8.1
//blog: http://blog.csdn.net/lecepin

@border-width:2px;
@loader-width:150px;
@loader-insider-width:@loader-width * 0.15;
@animate-time:4s;

*{
  margin: 0;
  padding: 0;
  border: 0;
}

html, body{
  width: 100%;
  height: 100%;
}

#loader{
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;

  p {
    padding: 1.5em;
    font-family: Arial;
  }

  .logo{
    width: @loader-width;
    height: @loader-width;
    position: relative;
    animation: spin @animate-time infinite;
    animation-direction: alternate;
    animation-timing-function:ease;

    &:before{
      position: absolute;
      content: '';
      left: 0;
      top: 0;
      border-color: transparent;
      border-width: @border-width;
      border-style: solid;
      animation: line-before @animate-time infinite;
      animation-direction: alternate;
    }

    &:after{
      position: absolute;
      content: '';
      bottom: -2 * @border-width;
      right: -2 * @border-width;
      border-color: transparent;
      border-width: @border-width;
      border-style: solid;
      animation: line-after @animate-time infinite;
      animation-direction: alternate;
    }

    .left{
      position: absolute;
      width: 50%;
      height: 100%;
      top: @border-width;
      right: 50%;
      background-color: #000;
      border-top-left-radius: 100% 50%;
      border-bottom-left-radius: 100% 50%;
      animation: left-right-fade @animate-time infinite;
      animation-direction: alternate;

      &:before{
        position: absolute;
        content: '';
        width: 100%;
        height: 50%;
        bottom: 0;
        left: 50%;
        border-radius: 50%;
        background-color: #000;
      }

      &:after{
        position: absolute;
        content: '';
        width: @loader-insider-width;
        height: @loader-insider-width;
        background-color: #fff;
        bottom: ~'calc(25% - @{loader-insider-width} / 2)';
        left: ~'calc(100% - @{loader-insider-width} / 2)';
        border-radius: 50%;
      }      
    }

    .right{
      position: absolute;
      width: 50%;
      height: 100%;
      top: @border-width;
      left: 50%;
      border-top-right-radius: 100% 50%;
      border-bottom-right-radius: 100% 50%;
      animation: left-right-fade @animate-time infinite;
      animation-direction: alternate;

      &:before{
        position: absolute;
        content: '';
        width: 100%;
        height: 50%;
        top: 0;
        right: 50%;
        border-radius: 50%;
        background-color: #fff;
      }

      &:after{
        position: absolute;
        content: '';
        width: @loader-insider-width;
        height: @loader-insider-width;
        background-color: #000;
        top: ~'calc(25% - @{loader-insider-width} / 2)';
        right: ~'calc(100% - @{loader-insider-width} / 2)';
        border-radius: 50%;
      }    
    }  
  }  
}

@keyframes line-before {
  0% {
    width: 0;
    height: 0;
    border-top-color: #000;
  }

  9.9% {
    border-right-color: transparent;
  }

  10% {
    width: 100%;
    border-right-color: #000;
    border-top-color: #000;
    height: 0;
  }

  20%,100% {
    width: 100%;
    border-right-color: #000;
    border-top-color: #000;
    height: 100%;
  }

  40% {
    width: 100%;
    border-right-color: #000;
    border-top-color: #000;
    height: 100%;
    border-radius: 0;
  }

  50%, 100% {
    width: 100%;
    border-right-color: #000;
    border-top-color: #000;
    height: 100%;
    border-radius: 50%;
  }
}

@keyframes line-after {
  0%,19.9% {
    border-color: transparent;
    width: 0;
    height: 0;
  }
  20% {
    width: 0;
    height: 0;
    border-bottom-color: #000;
  }

  29.9% {
    border-left-color: transparent;
  }

  30% {
    width: 100%;
    border-left-color: #000;
    border-bottom-color: #000;
    height: 0;
  }

  40% {
    width: 100%;
    border-left-color: #000;
    border-bottom-color: #000;
    height: 100%;
    border-radius: 0;
  }

  50%, 100% {
    border-radius: 50%;
    width: 100%;
    border-left-color: #000;
    border-bottom-color: #000;
    height: 100%;
  }
}

@keyframes left-right-fade {
  0%, 50%{
    opacity: 0;
  }

  75%, 100% {
    opacity: 1;
  }
}

@keyframes spin {
  0%, 75%{
    transform:rotate(0deg);
  }

  90%, 100% {
    transform:rotate(360deg);
  }
}

部落格名稱:王樂平部落格

CSDN部落格地址:http://blog.csdn.net/lecepin

知識共享許可協議
本作品採用 知識共享署名-非商業性使用-禁止演繹 4.0 國際許可協議進行許可。