Loading動效實現背後的思考過程

本着嚴肅認真的態度,聽取了你們的一些意見,對動畫流暢度及還原度作了優化css

有一個製做Loading動效的需求,設計師從AE導出了動畫JSON數據,但須要加載 lottie-web 才能播放,考慮到這種小動效並非業務中的常見需求,因此我不打算引入 lottie-web,而是直接根據動畫效果本身用CSS寫一個,記錄動效實現的思考過程。html

動效原型

觀察細節

  • 豎線在高度和寬度上有變化,位置上保持垂直居中,動畫時長1秒;
  • 堅線有上下漸變效果;
  • 從左到右的過程具備波浪效果;
  • 動畫的開始到結束是一個總體,只有最後一個豎線的動畫結束以後纔會開始下一輪動畫;
  • 每根豎線提伸到最高的時間和結束的時間都比它前一根要晚一點;

實現過程

一、靜態樣式

爲了實現寬度變化時,豎線之間不會互相影響,span 自己做爲容器,經過 after 僞類來實現動畫。git

.loading,
.loading > span {
    box-sizing: border-box;
}
.loading {
    font-size: 0;
    margin: auto;
    position: absolute;
    top: 0; left: 0; bottom: 0; right: 0;
    width: 110px;
    height: 75px;
    line-height: 75px;
    text-align: center;
    outline: 1px dashed #ccc;
}

.loading > span {
    display: inline-block;
    width: 22px;
    outline: 1px dashed #eee;
}

.loading > span::after {
    content: '';
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 5px;
    vertical-align: middle;
    background-image: linear-gradient(0deg, #00F4AA 0%, #0E85FF 100%);
}
複製代碼

二、實現波浪效果

通常的波浪效果實現上都是經過 animate-delay 讓每根豎線延遲開始動畫,但這裏動畫從開始到結束是一個總體,因此這裏咱們經過爲每一個豎線獨立設置動畫進度來實現,達到最高點的時間從前日後依次推遲10%,結束時間從後往前依次提早10%。github

.loading > span:nth-child(1)::after { animation: loadingAnim1 1s infinite ease; }
.loading > span:nth-child(2)::after { animation: loadingAnim2 1s infinite ease; }
.loading > span:nth-child(3)::after { animation: loadingAnim3 1s infinite ease; }
.loading > span:nth-child(4)::after { animation: loadingAnim4 1s infinite ease; }
.loading > span:nth-child(5)::after { animation: loadingAnim5 1s infinite ease; }

/* * Animation */
@keyframes loadingAnim1 {
    0% { height: 10px; }
    10% { height: 75px; }
    50% { height: 10px; }
}
@keyframes loadingAnim2 {
    0% { height: 10px; }
    20% { height: 75px; }
    60% { height: 10px; }
}
@keyframes loadingAnim3 {
    0% { height: 10px; }
    30% { height: 75px; }
    70% { height: 10px; }
}
@keyframes loadingAnim4 {
    0% { height: 10px; }
    40% { height: 75px; }
    80% { height: 10px; }
}
@keyframes loadingAnim5 {
    0% { height: 10px; }
    50% { height: 75px; }
    90% { height: 10px; }
}
複製代碼

三、設置不一樣的高度和寬度

每根豎線的最大拉伸高度不同,同時提伸後的寬度也會變小,相應的圓角也有變化web

@keyframes loadingAnim1 {
    0% { height: 10px; width: 10px; border-radius: 5px; }
    10% { height: 20px; width: 8px; border-radius: 4px; }
    50% { height: 10px; width: 10px; border-radius: 5px; }
}
@keyframes loadingAnim2 {
    0% { height: 10px; width: 10px; border-radius: 5px; }
    20% { height: 38px; width: 8px; border-radius: 4px; }
    60% { height: 10px; width: 10px; border-radius: 5px; }
}
@keyframes loadingAnim3 {
    0% { height: 10px; width: 10px; border-radius: 5px; }
    30% { height: 75px; width: 8px; border-radius: 4px; }
    70% { height: 10px; width: 10px; border-radius: 5px; }
}
@keyframes loadingAnim4 {
    0% { height: 10px; width: 10px; border-radius: 5px; }
    40% { height: 38px; width: 8px; border-radius: 4px; }
    80% { height: 10px; width: 10px; border-radius: 5px; }
}
@keyframes loadingAnim5 {
    0% { height: 10px; width: 10px; border-radius: 5px; }
    50% { height: 20px; width: 8px; border-radius: 4px; }
    90% { height: 10px; width: 10px; border-radius: 5px; }
}
複製代碼

四、最終樣式

.loading,
.loading > span {
    box-sizing: border-box;
}
.loading {
    font-size: 0;
    margin: auto;
    position: absolute;
    top: 0; left: 0; bottom: 0; right: 0;
    width: 110px;
    height: 75px;
    line-height: 75px;
    text-align: center;
}

.loading > span {
    display: inline-block;
    width: 22px;
}

.loading > span::after {
    content: '';
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 5px;
    vertical-align: middle;
    background-image: linear-gradient(0deg, #00F4AA 0%, #0E85FF 100%);
}
    
.loading > span:nth-child(1)::after { animation: loadingAnim1 1s infinite; }
.loading > span:nth-child(2)::after { animation: loadingAnim2 1s infinite; }
.loading > span:nth-child(3)::after { animation: loadingAnim3 1s infinite; }
.loading > span:nth-child(4)::after { animation: loadingAnim4 1s infinite; }
.loading > span:nth-child(5)::after { animation: loadingAnim5 1s infinite; }

/* * Animation */
@keyframes loadingAnim1 {
    0% { height: 10px; width: 10px; border-radius: 5px; }
    10% { height: 20px; width: 8px; border-radius: 4px; }
    50% { height: 10px; width: 10px; border-radius: 5px; }
}
@keyframes loadingAnim2 {
    0% { height: 10px; width: 10px; border-radius: 5px; }
    20% { height: 38px; width: 8px; border-radius: 4px; }
    60% { height: 10px; width: 10px; border-radius: 5px; }
}
@keyframes loadingAnim3 {
    0% { height: 10px; width: 10px; border-radius: 5px; }
    30% { height: 75px; width: 8px; border-radius: 4px; }
    70% { height: 10px; width: 10px; border-radius: 5px; }
}
@keyframes loadingAnim4 {
    0% { height: 10px; width: 10px; border-radius: 5px; }
    40% { height: 38px; width: 8px; border-radius: 4px; }
    80% { height: 10px; width: 10px; border-radius: 5px; }
}
@keyframes loadingAnim5 {
    0% { height: 10px; width: 10px; border-radius: 5px; }
    50% { height: 20px; width: 8px; border-radius: 4px; }
    90% { height: 10px; width: 10px; border-radius: 5px; }
}
複製代碼

最終效果展現


I'm Gafish 原創文章,首發於 個人博客,內容若有錯誤,還望指正,謝謝您的閱讀。優化

相關文章
相關標籤/搜索