Material Design的Loading动画

作者: im宇 | 来源:发表于2016-10-04 15:36 被阅读1157次

写在前面:
这是一篇菜鸟的学习笔记,记录效果实现过程,而没有考虑安全、兼容、性等问题。供新手参考,也希望前辈们指点。

这篇文章将一步一步记录实现一个Material Design的Loading动画,该效果模仿自Materialize网站的Loading动画,效果如下:

Materialize网站的效果.gif 我的最终效果.gif

Loading链接展示

实现的小思路:

之前一直在想通过border的方法只能是实现一个完整的圆圈(或缺n*45°的圆圈),但是上面的效果明显是一个可变长度的圆圈的一部分,那么该如何实现呢?后来查看了下Materialize网站Loading部分的css布局。发现原来是另一种思路的实现。Materialize是通过一个小div设置overflow:hidden属性将圆圈的一半给挡住,然后在同个border-left等属性使圆圈只有一半,这样结合transform: rotate()属性选择这一半的圆圈就可以实现非完整圆圈了。而实际上实现上图任意程度的非完整圆圈,需要使用两个div分别各占布局的左右以及两个半圆来实现。具体如何使用,参考详解用CSS3制作圆形滚动进度条动画效果

第一部分动画(去掉外布局旋转的效果)

  • 先来看看Materialize的效果:
去掉外布局旋转的效果.gif
  • 我的实现效果:
动画一.gif
  • 我的实现思路:
    大布局下分为两个div,两个div下又有各自的圆圈。同时设置旋转动画以达到该效果。
  • 实现代码:
<!DOCTYPE html>
<html>
<head>
    <mate charset="utf-8"></mate>
    <title>Material Design Loading Animation</title>
    <style>
        /*外层布局*/
        .circle-layout{
            width: 110px;
            height: 110px;
        }
        /*左div*/
        .layout-left{
            float: left;
            width: 50%;
            height: 100%;
            overflow: hidden;
            position: relative;
        }
        /*右div*/
        .layout-right{
            float: right;
            width: 50%;
            height: 100%;
            overflow: hidden;
            position: relative;
        }
        /*左圈*/
        .circle-left{
            position: absolute;
            top: 0;
            left: 0;
            width: 100px;
            height: 100px;
            border: 5px solid #F88E8B;
            border-radius: 50%;
            border-left: 5px solid transparent;
            border-bottom: 5px solid transparent;
            transform: rotate(40deg);
            animation: animation-circle-left 1s cubic-bezier(0.4, 0, 0.2, 1) infinite;
        }
        /*右圈*/
        .circle-right{
            position: absolute;
            top: 0;
            right: 0;
            width: 100px;
            height: 100px;
            border: 5px solid #F88E8B;
            border-radius: 50%;
            border-right: 5px solid transparent;
            border-top: 5px solid transparent;
            transform: rotate(-310deg);
            animation: animation-circle-right 1s cubic-bezier(0.4, 0, 0.2, 1) infinite;
        }
        /*左圈动画*/
        @keyframes animation-circle-left{
            0%{
                transform: rotate(40deg);
            }
            50%{
                transform: rotate(-100deg);
            }
            100%{
                transform: rotate(40deg);
            }
        }
        /*右圈动画*/
        @keyframes animation-circle-right{
            0%{
                transform: rotate(-310deg);
            }
            50%{
                transform: rotate(-170deg);
            }
            100%{
                transform: rotate(-310deg);
            }
        }
    </style>
</head>
<body>
    <div class="circle-layout">
        <div class="layout-left">
            <div class="circle-left"></div>
        </div>
        <div class="layout-right">
            <div class="circle-right"></div>
        </div>
    <div>
</body>
</html>

第二部分动画(加上外层布局旋转的效果)

  • 先来看看Materialize的效果:
加上外布局旋转的效果.gif
  • 我的实现效果:
动画二.gif
  • 我的实现思路:
    仔细看就会发现这个动画是先从一个点往前进方向伸张,然后又从尾部开始往前进方向收缩成一个点。那么如何通过上面“去掉外布局旋转的效果”基本动画得到“加上外布局旋转的效果”动画呢?从名字当中就可以看出来,答案就是加上外布局的旋转。外布局的动画时间是基本动画时间的两倍,总旋转角度为720°,旋转速度大致与“基本动画”相当(本来应该是一致,但注意到“基本动画”的圆圈伸张距离并没有达到360°,而外布局的动画又要在周期之间灰度过度)。
    细心的人会注意到“加上外布局旋转的效果”与“动画二”的效果不大一样:前者的圆圈缺口方向会改变,二后者的方向一直向上。好吧,我承认是我不知道如何做到前者的效果。但看下面“动画三”的效果与Materialize的效果还是比较像的,先这样凑合用着吧!_

  • 代码实现:

<!DOCTYPE html>
<html>
<head>
    <mate charset="utf-8"></mate>
    <title>Material Design Loading Animation</title>
    <style>
        /*外层布局*/
        .circle-layout{
            width: 110px;
            height: 110px;
            animation: animation-circle 4s cubic-bezier(0.4, 0, 0.2, 1) infinite;
        }
        /*左div*/
        .layout-left{
            float: left;
            width: 50%;
            height: 100%;
            overflow: hidden;
            position: relative;
        }
        /*右div*/
        .layout-right{
            float: right;
            width: 50%;
            height: 100%;
            overflow: hidden;
            position: relative;
        }
        /*左圈*/
        .circle-left{
            position: absolute;
            top: 0;
            left: 0;
            width: 100px;
            height: 100px;
            border: 5px solid #F88E8B;
            border-radius: 50%;
            border-left: 5px solid transparent;
            border-bottom: 5px solid transparent;
            transform: rotate(40deg);
            animation: animation-circle-left 2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
        }
        /*右圈*/
        .circle-right{
            position: absolute;
            top: 0;
            right: 0;
            width: 100px;
            height: 100px;
            border: 5px solid #F88E8B;
            border-radius: 50%;
            border-right: 5px solid transparent;
            border-top: 5px solid transparent;
            transform: rotate(-310deg);
            animation: animation-circle-right 2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
        }
        /*左圈动画*/
        @keyframes animation-circle-left{
            0%{
                transform: rotate(40deg);
            }
            50%{
                transform: rotate(-100deg);
            }
            100%{
                transform: rotate(40deg);
            }
        }
        /*右圈动画*/
        @keyframes animation-circle-right{
            0%{
                transform: rotate(-310deg);
            }
            50%{
                transform: rotate(-170deg);
            }
            100%{
                transform: rotate(-310deg);
            }
        }
        /*外层动画*/
        @keyframes animation-circle{
            0%{
                transform: rotate(0deg);
            }
            25%{
                transform: rotate(180deg);
            }
            50%{
                transform: rotate(360deg);
            }
            75%{
                transform: rotate(540deg);
            }
            100%{
                transform: rotate(720deg);
            }
        }
        
    </style>
</head>
<body>
    <div class="circle-layout">
        <div class="layout-left">
            <div class="circle-left"></div>
        </div>
        <div class="layout-right">
            <div class="circle-right"></div>
        </div>
    <div>
</body>
</html>

第三部分动画(在加一个最外层布局)

  • 先来看看Materialize的效果:
在加最外层布局旋转的效果.gif
  • 我的实现效果:
动画三.gif
  • 我的实现思路:
    “动画三”只是在“动画二”的基础上加上了一层旋转,以达到圆圈缺口方向的变化仅此而已。至于圆圈缺口的变化,读者可自行修改animation-wrap动画以及animation-circle动画的时间以调整效果,但是必须保证animation-circle的动画时间一定是animation-circle-left/right的两倍。

  • 实现代码:

<!DOCTYPE html>
<html>
<head>
    <mate charset="utf-8"></mate>
    <title>Material Design Loading Animation</title>
    <style>
    body{
        margin: 100px 200px;
    }
        /*最外层布局*/
        .wrap{
            width: 110px;
            height: 110px;
            animation: animation-wrap 2.5s linear infinite;
        }
        /*外层布局*/
        .circle-layout{
            width: 110px;
            height: 110px;
            animation: animation-circle 3s cubic-bezier(0.4, 0, 0.2, 1) infinite;
        }
        /*左div*/
        .layout-left{
            float: left;
            width: 50%;
            height: 100%;
            overflow: hidden;
            position: relative;
        }
        /*右div*/
        .layout-right{
            float: right;
            width: 50%;
            height: 100%;
            overflow: hidden;
            position: relative;
        }
        /*左圈*/
        .circle-left{
            position: absolute;
            top: 0;
            left: 0;
            width: 100px;
            height: 100px;
            border: 5px solid #F88E8B;
            border-radius: 50%;
            border-left: 5px solid transparent;
            border-bottom: 5px solid transparent;
            transform: rotate(40deg);
            animation: animation-circle-left 1.5s cubic-bezier(0.4, 0, 0.2, 1) infinite;
        }
        /*右圈*/
        .circle-right{
            position: absolute;
            top: 0;
            right: 0;
            width: 100px;
            height: 100px;
            border: 5px solid #F88E8B;
            border-radius: 50%;
            border-right: 5px solid transparent;
            border-top: 5px solid transparent;
            transform: rotate(-310deg);
            animation: animation-circle-right 1.5s cubic-bezier(0.4, 0, 0.2, 1) infinite;
        }
        /*左圈动画*/
        @keyframes animation-circle-left{
            0%{
                transform: rotate(40deg);
            }
            50%{
                transform: rotate(-100deg);
            }
            100%{
                transform: rotate(40deg);
            }
        }
        /*右圈动画*/
        @keyframes animation-circle-right{
            0%{
                transform: rotate(-310deg);
            }
            50%{
                transform: rotate(-170deg);
            }
            100%{
                transform: rotate(-310deg);
            }
        }
        /*外层动画*/
        @keyframes animation-circle{
            0%{
                transform: rotate(0deg);
            }
            25%{
                transform: rotate(180deg);
            }
            50%{
                transform: rotate(360deg);
            }
            75%{
                transform: rotate(540deg);
            }
            100%{
                transform: rotate(720deg);
            }
        }
        /*最外层动画*/
        @keyframes animation-wrap{
            0%{
                transform: rotate(0deg);
            }
            100%{
                transform: rotate(360deg);
            }
        }
        
    </style>
</head>
<body>
    <div class="wrap">
        <div class="circle-layout">
            <div class="layout-left">
                <div class="circle-left"></div>
            </div>
            <div class="layout-right">
                <div class="circle-right"></div>
            </div>
        <div>
    </div>
</body>
</html>

后续内容

将该效果封装成可复用且方便使用的控件,打算使用js动态生成众多的布局减少html中的代码量。


更新,2016.10.6
完成后续内容,同时增加可设置大小颜色功能


最终效果如下:

是不是和Materialize网站的很接近了。_

最终效果.gif

代码如下:

<!DOCTYPE html>
<html>
<head>
    <mate charset="utf-8"></mate>
    <title>Material Design Loading Animation</title>
    <link rel="stylesheet" type="text/css" href="loading.css"></link>
    <script type="text/javascript" src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
    <script>
        $(document).ready(function(){
            function LoadingClass(){
                this.wrap = jQuery(".mmd-loading-wrap");
                this.run = function(){
                    this.wrap.each(function(i){
                    
                        //计算圆圈的宽度
                        var bw = Math.round($(this).width()/15);
                        var w = $(this).width() - 2 * bw;
                        //通过自定义属性得到圆圈的颜色
                        var circleColor = $(this).attr("circleColor");
                        
                        //动态生成圆圈。即将上一个版本中html的代码搬移到js中,减低html代码使用量
                        var div = "<div class='mmd-loading-circle-layout'>"
                              +"<div class='mmd-loading-layout-left'>"
                                +"<div class='mmd-loading-circle-left'"
                                    +"style='width:"+w+"px;height:"+w+"px;border-width:"+bw+"px;border-color:"+circleColor+";"
                                        +"border-left:"+bw+"px solid transparent;"+"border-bottom:"+bw+"px solid transparent;'"+"></div>"
                              +"</div>"
                              +"<div class='mmd-loading-layout-right'>"
                                +"<div class='mmd-loading-circle-right'"
                                    +"style='width:"+w+"px;height:"+w+"px;border-width:"+bw+"px;border-color:"+circleColor+";"
                                        +"border-right:"+bw+"px solid transparent;"+"border-top:"+bw+"px solid transparent;'"+"></div>"
                              +"</div>"
                          +"</div>";
                        $(this).append(div);
                    });
                }
            }
            //自动运行
            (function(){
                var loading = new LoadingClass();
                loading.run();
            })();
        });
    </script>
</head>
<body>
    <!-- 需要设置circleColor -->
    <div class="mmd-loading-wrap" style="width:60px;height:60px;position:absolute;left:300px;top:100px;" circleColor="#F88E8B"></div>
    <div class="mmd-loading-wrap" style="width:40px;height:40px;position:absolute;left:500px;top:100px;" circleColor="#DC4C40"></div>
    <div class="mmd-loading-wrap" style="width:30px;height:30px;position:absolute;left:700px;top:100px;" circleColor="#26A668"></div>
</body>
</html>

附上源码:

Loading示例代码

相关文章

网友评论

    本文标题:Material Design的Loading动画

    本文链接:https://www.haomeiwen.com/subject/iowjyttx.html