Material Design的Loading动画

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

这篇文章将一步一步记录实现一个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示例代码

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容

  • 各种纯css图标 CSS3可以实现很多漂亮的图形,我收集了32种图形,在下面列出。直接用CSS3画出这些图形,要比...
    剑残阅读 9,174评论 0 8
  • 1.长方形 #Rectangle{ width: 200px; height: 50px; background-...
    一直以来都很好阅读 462评论 0 0
  • 1、垂直对齐 如果你用CSS,则你会有困惑:我该怎么垂直对齐容器中的元素?现在,利用CSS3的Transform,...
    kiddings阅读 3,104评论 0 11
  • 选择qi:是表达式 标签选择器 类选择器 属性选择器 继承属性: color,font,text-align,li...
    love2013阅读 2,279评论 0 11
  • 无意间看见昨日 曾经的刻骨铭心 却已不及梦境的幻影清晰 记忆戏弄了经历 轮回编造着痴迷的故事 来到今日 去寻找清明...
    岳Domke阅读 304评论 0 2