写在前面:
这是一篇菜鸟的学习笔记,记录效果实现过程,而没有考虑安全、兼容、性等问题。供新手参考,也希望前辈们指点。
这篇文章将一步一步记录实现一个Material Design的Loading动画,该效果模仿自Materialize网站的Loading动画,效果如下:
Materialize网站的效果.gif 我的最终效果.gif实现的小思路:
之前一直在想通过border的方法只能是实现一个完整的圆圈(或缺n*45°的圆圈),但是上面的效果明显是一个可变长度的圆圈的一部分,那么该如何实现呢?后来查看了下Materialize网站Loading部分的css布局。发现原来是另一种思路的实现。Materialize是通过一个小div设置overflow:hidden属性将圆圈的一半给挡住,然后在同个border-left等属性使圆圈只有一半,这样结合transform: rotate()属性选择这一半的圆圈就可以实现非完整圆圈了。而实际上实现上图任意程度的非完整圆圈,需要使用两个div分别各占布局的左右以及两个半圆来实现。具体如何使用,参考详解用CSS3制作圆形滚动进度条动画效果
第一部分动画(去掉外布局旋转的效果)
- 先来看看Materialize的效果:
- 我的实现效果:
- 我的实现思路:
大布局下分为两个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的效果:
- 我的实现效果:
-
我的实现思路:
仔细看就会发现这个动画是先从一个点往前进方向伸张,然后又从尾部开始往前进方向收缩成一个点。那么如何通过上面“去掉外布局旋转的效果”基本动画得到“加上外布局旋转的效果”动画呢?从名字当中就可以看出来,答案就是加上外布局的旋转。外布局的动画时间是基本动画时间的两倍,总旋转角度为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的效果:
- 我的实现效果:
-
我的实现思路:
“动画三”只是在“动画二”的基础上加上了一层旋转,以达到圆圈缺口方向的变化仅此而已。至于圆圈缺口的变化,读者可自行修改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>
网友评论