以下是 基于SVG实现Loading加载按钮代码 的示例演示效果:
部分效果截图1:
部分效果截图2:
HTML代码(index.html):
<!doctype html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>基于SVG实现Loading加载按钮代码</title>
<link rel="stylesheet" type="text/css" href="css/normalize.css" />
<link rel="stylesheet" type="text/css" href="css/demo.css" />
<link rel="stylesheet" type="text/css" href="css/zzsc-demo.css">
<script src="js/classie.js"></script>
<script src="js/segment.js"></script>
<script src="js/loading-button.js"></script>
</head>
<body>
<section class="zzsc-container">
<div class="container">
<h1 class="demo-title">基于SVG实现Loading加载按钮代码</h1>
<div class="showcase main-showcase">
<button class="control-button bordered make-it-fail">Make it fail</button>
<button class="loading-button circular-loading top">Send</button>
<button class="control-button bordered make-it-succeed">Make it succeed</button>
</div>
<div class="loading-options">
<div class="loaders">
<h2>Loaders</h2>
<label>
<input type="radio" name="loaders" value="circular-loading" checked="checked"/>
<span>circular</span>
</label>
<label>
<input type="radio" name="loaders" value="circle-loading"/>
<span>circle</span>
</label>
<label>
<input type="radio" name="loaders" value="infinity-loading"/>
<span>infinity</span>
</label>
</div>
<div class="positions">
<h2>Positions</h2>
<label>
<input type="radio" name="positions" value="top" checked="checked"/>
<span>top</span>
</label>
<label>
<input type="radio" name="positions" value="bottom"/>
<span>bottom</span>
</label>
<label>
<input type="radio" name="positions" value="left"/>
<span>left</span>
</label>
<label>
<input type="radio" name="positions" value="right"/>
<span>right</span>
</label>
</div>
</div>
</div>
</section>
<script type="text/template" id="circular-loading">
<svg width="120px" height="120px">
<path class="outer-path" stroke="#fff" d="M 60 60 m 0 -50 a 50 50 0 1 1 0 100 a 50 50 0 1 1 0 -100"></path>
<path class="inner-path" stroke="rgba(255, 255, 255, 0.5)" d="M 60 60 m 0 -30 a 30 30 0 1 1 0 60 a 30 30 0 1 1 0 -60"></path>
<path class="success-path" stroke="#fff" d="M 60 10 A 50 50 0 0 1 91 21 L 75 45 L 55 75 L 45 65"></path>
<path class="error-path" stroke="#fff" d="M 60 10 A 50 50 0 0 1 95 25 L 45 75"></path>
<path class="error-path2" stroke="#fff" d="M 60 30 A 30 30 0 0 1 81 81 L 45 45"></path>
</svg>
</script>
<script type="text/template" id="circle-loading">
<svg width="120px" height="120px">
<circle r="50" cx="60" cy="60" fill="none" stroke="rgba(255, 255, 255, 0.3)"></circle>
<circle r="30" cx="60" cy="60" fill="none" stroke="rgba(255, 255, 255, 0.3)"></circle>
<path class="outer-path" stroke="#fff" d="M 60 60 m 0 -50 a 50 50 0 1 1 0 100 a 50 50 0 1 1 0 -100"></path>
<path class="inner-path" stroke="#fff" d="M 60 60 m 0 -30 a 30 30 0 1 1 0 60 a 30 30 0 1 1 0 -60"></path>
<path class="success-path" stroke="#fff" d="M 60 10 A 50 50 0 0 0 16 36 L 45 65 L 55 75 L 75 45"></path>
<path class="error-path" stroke="#fff" d="M 60 10 A 50 50 0 0 0 25 95 L 75 45"></path>
<path class="error-path2" stroke="#fff" d="M 60 30 A 30 30 0 0 1 81 81 L 45 45"></path>
</svg>
</script>
<script type="text/template" id="infinity-loading">
<svg width="120px" height="60px">
<path class="infinity-path" stroke="#fff" d="M 30 10 a 20 20 0 1 0 0 40 c 20 0 40 -40 60 -40 a 20 20 0 0 1 0 40 c -20 0 -40 -40 -60 -40"></path>
<path class="success-path" stroke="#fff" d="M 30 10 C 15 10 35 25 45 35 L 55 45 L 75 15"></path>
<path class="error-path" stroke="#fff" d="M 30 10 a 20 20 0 1 0 0 40 Q 40 50 45 45 L 75 15"></path>
<path class="error-path2" stroke="#fff" d="M 30 10 Q 40 10 45 15 L 75 45"></path>
</svg>
</script>
<script src="js/demo-functions.js"></script>
<script src="js/demo.js"></script>
</body>
</html>
JS代码(demo.js):
(function(){
function clean(button,value){
loading.infinite = false;
button.innerHTML = button.querySelector('span').innerHTML;
classie.remove(button,current);
classie.add(button,value);
current = value;
var newButton = button.cloneNode(true);
button.parentNode.replaceChild(newButton,button);
return newButton;
}
function newLoader(button,value,open){
var newButton = clean(button,value);
if(value === 'circular-loading'){
loading = circularLoading();
}
else if(value === 'infinity-loading'){
loading = infinityLoading();
}
else if(value === 'circle-loading'){
loading = circleLoading();
}
if(open){
newButton.removeAttribute('disabled');
setTimeout(function(){
newButton.click();
}
,300);
}
}
function loadersClick(){
var self = this;
var button = document.querySelector('.loading-button');
if(classie.has(button,'open-loading')){
classie.remove(button,'open-loading');
setTimeout(function(){
newLoader(button,self.value,true);
}
,300);
}
else{
newLoader(button,self.value);
}
}
var loaders = document.getElementsByName('loaders'),current = 'circular-loading';
for(var i = 0;
i < loaders.length;
i++){
loaders[i].addEventListener('change',loadersClick,false);
}
var loading = circularLoading();
function positionsClick(){
var button = document.querySelector('.loading-button');
classie.add(button,'no-transition');
classie.remove(button,currentStyle);
classie.add(button,this.value);
currentStyle = this.value;
setTimeout(function(){
classie.remove(button,'no-transition');
}
,10);
}
var positions = document.getElementsByName('positions'),currentStyle = 'top';
for(i = 0;
i < positions.length;
i++){
positions[i].addEventListener('change',positionsClick,false);
}
}
)();
JS代码(segment.js):
/** * segment - A little JavaScript class (without dependencies) to draw and animate SVG path strokes * @version v1.0 * @link https://github.com/lmgonzalves/segment * @license MIT */
(function(){
var lastTime = 0;
var vendors = ['ms','moz','webkit','o'];
for(var x = 0;
x < vendors.length && !window.requestAnimationFrame;
++x){
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
}
if(!window.requestAnimationFrame) window.requestAnimationFrame = function(callback,element){
var currTime = new Date().getTime();
var timeToCall = Math.max(0,16 - (currTime - lastTime));
var id = window.setTimeout(function(){
callback(currTime + timeToCall);
}
,timeToCall);
lastTime = currTime + timeToCall;
return id;
}
;
if(!window.cancelAnimationFrame) window.cancelAnimationFrame = function(id){
clearTimeout(id);
}
;
}
());
function Segment(path,begin,end){
this.path = path;
this.length = path.getTotalLength();
this.path.style.strokeDashoffset = this.length * 2;
this.begin = typeof begin !== 'undefined' ? this.valueOf(begin):0;
this.end = typeof end !== 'undefined' ? this.valueOf(end):this.length;
this.circular = false;
this.timer = null;
this.draw(this.begin,this.end);
}
Segment.prototype ={
draw:function(begin,end,duration,options){
if(duration){
var delay = options && options.hasOwnProperty('delay') ? parseFloat(options.delay) * 1000:0,easing = options && options.hasOwnProperty('easing') ? options.easing:null,callback = options && options.hasOwnProperty('callback') ? options.callback:null,that = this;
this.circular = options && options.hasOwnProperty('circular') ? options.circular:false;
this.stop();
if(delay){
delete options.delay;
this.timer = setTimeout(function(){
that.draw(begin,end,duration,options);
}
,delay);
return this.timer;
}
var startTime = new Date(),initBegin = this.begin,initEnd = this.end,finalBegin = this.valueOf(begin),finalEnd = this.valueOf(end);
(function calc(){
var now = new Date(),elapsed = (now-startTime)/1000,time = (elapsed/parseFloat(duration)),t = time;
if(typeof easing === 'function'){
t = easing(t);
}
if(time > 1){
t = 1;
}
else{
that.timer = window.requestAnimationFrame(calc);
}
that.begin = initBegin + (finalBegin - initBegin) * t;
that.end = initEnd + (finalEnd - initEnd) * t;
that.begin = that.begin < 0 && !that.circular ? 0:that.begin;
that.begin = that.begin > that.length && !that.circular ? that.length:that.begin;
that.end = that.end < 0 && !that.circular ? 0:that.end;
that.end = that.end > that.length && !that.circular ? that.length:that.end;
if(that.end - that.begin < that.length && that.end - that.begin > 0){
that.draw(that.begin,that.end);
}
else{
if(that.circular && that.end - that.begin > that.length){
that.draw(0,that.length);
}
else{
that.draw(that.begin + (that.end - that.begin),that.end - (that.end - that.begin));
}
}
if(time > 1 && typeof callback === 'function'){
return callback.call(that);
}
}
)();
}
else{
this.path.style.strokeDasharray = this.strokeDasharray(begin,end);
}
}
,strokeDasharray:function(begin,end){
this.begin = this.valueOf(begin);
this.end = this.valueOf(end);
if(this.circular){
var division = this.begin > this.end || (this.begin < 0 && this.begin < this.length * -1) ? parseInt(this.begin / parseInt(this.length)):parseInt(this.end / parseInt(this.length));
if(division !== 0){
this.begin = this.begin - this.length * division;
this.end = this.end - this.length * division;
}
}
if(this.end > this.length){
var plus = this.end - this.length;
return [this.length,this.length,plus,this.begin - plus,this.end - this.begin].join(' ');
}
if(this.begin < 0){
var minus = this.length + this.begin;
if(this.end < 0){
return [this.length,this.length + this.begin,this.end - this.begin,minus - this.end,this.end - this.begin,this.length].join(' ');
}
else{
return [this.length,this.length + this.begin,this.end - this.begin,minus - this.end,this.length].join(' ');
}
}
return [this.length,this.length + this.begin,this.end - this.begin].join(' ');
}
,valueOf:function(input){
var val = parseFloat(input);
if(typeof input === 'string' || input instanceof String){
if(~input.indexOf('%')){
var arr;
if(~input.indexOf('+')){
arr = input.split('+');
val = this.percent(arr[0]) + parseFloat(arr[1]);
}
else if(~input.indexOf('-')){
arr = input.split('-');
val = arr[0] ? this.percent(arr[0]) - parseFloat(arr[1]):-this.percent(arr[1]);
}
else{
val = this.percent(input);
}
}
}
return val;
}
,stop:function(){
window.cancelAnimationFrame(this.timer);
this.timer = null;
}
,percent:function(value){
return parseFloat(value) / 100 * this.length;
}
}
;
CSS代码(demo.css):
body{font-family:Avenir,'Helvetica Neue','Lato','Segoe UI',Helvetica,Arial,sans-serif;color:#eee;background:#354458;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;}
a{color:rgba(255,255,255,0.8);text-decoration:none;border-bottom:1px solid transparent;-webkit-transition:0.3s;transition:0.3s;}
a:hover{color:#fff;border-bottom-color:#fff;}
.container{text-align:center;}
h1.demo-title{position:relative;display:inline-block;margin:50px 0 0;}
h1.demo-title:before,h1.demo-title:after{content:'';position:absolute;top:50%;width:30px;height:1px;background-color:rgba(255,255,255,0.8);}
h1.demo-title:before{left:-50px;}
h1.demo-title:after{right:-50px;}
.demo-subtitle{margin:5px 0 40px;color:rgba(255,255,255,0.4);}
.description{color:rgba(255,255,255,0.7);}
.showcase{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;margin-top:50px;}
.showcase button{position:relative;display:inline-block;min-width:160px;border:none;background-color:#3A9AD9;color:#ffffff;letter-spacing:1px;text-transform:uppercase;cursor:pointer;padding:10px 20px;margin:0 10px;border-radius:2px;-webkit-transition:0.3s;transition:0.3s;}
.showcase button:not([disabled]):hover{background-color:#4fa7dd;}
.showcase button.bordered{background-color:transparent;border:2px solid #3A9AD9;padding:8px 0;}
.showcase button.bordered:not([disabled]):hover{background-color:#3A9AD9;border-color:transparent;}
.showcase button.control-button{width:170px;font-size:13px;visibility:hidden;opacity:0;-webkit-transition:0.5s 0s opacity,0.1s visibility;transition:0.5s 0s opacity,0.1s visibility;}
.showcase button.control-button.show-control{visibility:visible;opacity:1;-webkit-transition:0.5s 0.4s opacity,0.3s background,0.3s border;transition:0.5s 0.4s opacity,0.3s background,0.3s border;}
.showcase button.control-button.make-it-fail{border-color:#EB7260;}
.showcase button.control-button.make-it-fail:hover{background-color:#EB7260;}
.showcase button.control-button.make-it-succeed{border-color:#29ABA4;}
.showcase button.control-button.make-it-succeed:hover{background-color:#29ABA4;}
.loading-button.open-loading{color:rgba(255,255,255,0.8);}
.loading-button.open-loading.infinity{padding-top:80px;}
.loading-button.open-loading svg{display:inline-block;visibility:visible;opacity:1;-webkit-transition:1s opacity;transition:1s opacity;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);}
.loading-button.failed{background-color:#EB7260;}
.loading-button.succeed{background-color:#29ABA4;}
.loading-button.no-transition{-webkit-transition:0s;transition:0s;}
.loading-button.no-transition *{-webkit-transition:0s;transition:0s;}
.loading-button svg{visibility:hidden;position:absolute;left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);opacity:0;-webkit-transition:0s;transition:0s;}
.loading-button svg path{stroke-linecap:round;stroke-linejoin:round;stroke-width:4;fill:none;}
.loading-button svg path.success-path,.loading-button svg path.error-path,.loading-button svg path.error-path2{visibility:hidden;}
.loading-button.top svg{top:10px;}
.loading-button.bottom svg{bottom:10px;}
.loading-button.left svg{top:50%;-webkit-transform:scale(0.25) translateY(-50%);-ms-transform:scale(0.25) translateY(-50%);transform:scale(0.25) translateY(-50%);-webkit-transform-origin:0 0 0;-ms-transform-origin:0 0 0;transform-origin:0 0 0;left:20px;}
.loading-button.right svg{top:50%;-webkit-transform:scale(0.25) translateY(-50%);-ms-transform:scale(0.25) translateY(-50%);transform:scale(0.25) translateY(-50%);-webkit-transform-origin:100% 0 0;-ms-transform-origin:100% 0 0;transform-origin:100% 0 0;left:auto;right:20px;}
.loading-button.open-loading.left{padding-left:60px;}
.loading-button.open-loading.right{padding-right:60px;}
.loading-button.open-loading.top svg,.loading-button.open-loading.bottom svg{-webkit-transition-delay:0.2s;transition-delay:0.2s;}
.loading-button.open-loading.circular-loading.top,.loading-button.open-loading.circle-loading.top{padding-top:140px;}
.loading-button.open-loading.circular-loading.bottom,.loading-button.open-loading.circle-loading.bottom{padding-bottom:140px;}
.loading-button.open-loading.infinity-loading.top{padding-top:80px;}
.loading-button.open-loading.infinity-loading.bottom{padding-bottom:80px;}
.loading-options{text-align:center;}
.loading-options > div{display:inline-block;width:40%;cursor:default;}
.loading-options label{display:inline-block;margin:0 5px;cursor:pointer;}
.loading-options label input{display:none;}
.loading-options label input:checked + span{background-color:rgba(0,0,0,0.5);}
.loading-options label span{display:inline-block;padding:5px 10px;font-size:13px;letter-spacing:1px;text-transform:uppercase;border-radius:2px;background-color:rgba(0,0,0,0.3);}
.circle-loading circle{visibility:hidden;opacity:0;-webkit-transition:0.5s;transition:0.5s;}
.circle-loading.show-circles circle{visibility:visible;opacity:1;}
CSS代码(zzsc-demo.css):
body{background:#494A5F;color:#D5D6E2;font-weight:500;font-size:1.05em;font-family:"Microsoft YaHei","宋体","Segoe UI","Lucida Grande",Helvetica,Arial,sans-serif,FreeSans,Arimo;}
a{color:#2fa0ec;text-decoration:none;outline:none;}
a:hover,a:focus{color:#74777b;}
.zzsc-container{margin:0 auto;text-align:center;overflow:hidden;}
.zzsc-content{font-size:150%;padding:1em 0;}
.zzsc-content h2{margin:0 0 2em;opacity:0.1;}
.zzsc-content p{margin:1em 0;padding:5em 0 0 0;font-size:0.65em;}
.bgcolor-1{background:#f0efee;}
.bgcolor-2{background:#f9f9f9;}
.bgcolor-3{background:#e8e8e8;}
/*light grey*/
.bgcolor-4{background:#2f3238;color:#fff;}
/*Dark grey*/
.bgcolor-5{background:#df6659;color:#521e18;}
/*pink1*/
.bgcolor-6{background:#2fa8ec;}
/*sky blue*/
.bgcolor-7{background:#d0d6d6;}
/*White tea*/
.bgcolor-8{background:#3d4444;color:#fff;}
/*Dark grey2*/
.bgcolor-9{background:#ef3f52;color:#fff;}
/*pink2*/
.bgcolor-10{background:#64448f;color:#fff;}
/*Violet*/
.bgcolor-11{background:#3755ad;color:#fff;}
/*dark blue*/
.bgcolor-12{background:#3498DB;color:#fff;}
/*light blue*/
.bgcolor-20{background:#494A5F;color:#D5D6E2;}
/* Header */
.zzsc-header{padding:1em 190px 1em;letter-spacing:-1px;text-align:center;background:#66677c;}
.zzsc-header h1{color:#D5D6E2;font-weight:600;font-size:2em;line-height:1;margin-bottom:0;font-family:"Microsoft YaHei","宋体","Segoe UI","Lucida Grande",Helvetica,Arial,sans-serif,FreeSans,Arimo;}
.zzsc-header h1 span{font-family:"Microsoft YaHei","宋体","Segoe UI","Lucida Grande",Helvetica,Arial,sans-serif,FreeSans,Arimo;display:block;font-size:60%;font-weight:400;padding:0.8em 0 0.5em 0;color:#c3c8cd;}
/*nav*/
.zzsc-demo a{color:#1d7db1;text-decoration:none;}
.zzsc-demo{width:100%;padding-bottom:1.2em;}
.zzsc-demo a{display:inline-block;margin:0.5em;padding:0.6em 1em;border:3px solid #1d7db1;font-weight:700;}
.zzsc-demo a:hover{opacity:0.6;}
.zzsc-demo a.current{background:#1d7db1;color:#fff;}
/* Top Navigation Style */
.zzsc-links{position:relative;display:inline-block;white-space:nowrap;font-size:1.5em;text-align:center;}
.zzsc-links::after{position:absolute;top:0;left:50%;margin-left:-1px;width:2px;height:100%;background:#dbdbdb;content:'';-webkit-transform:rotate3d(0,0,1,22.5deg);transform:rotate3d(0,0,1,22.5deg);}
.zzsc-icon{display:inline-block;margin:0.5em;padding:0em 0;width:1.5em;text-decoration:none;}
.zzsc-icon span{display:none;}
.zzsc-icon:before{margin:0 5px;text-transform:none;font-weight:normal;font-style:normal;font-variant:normal;font-family:'icomoon';line-height:1;speak:none;-webkit-font-smoothing:antialiased;}
/* footer */
.zzsc-footer{width:100%;padding-top:10px;}
.zzsc-small{font-size:0.8em;}
.center{text-align:center;}
/****/
.related{color:#fff;background:#494A5F;text-align:center;font-size:1.25em;padding:0.5em 0;overflow:hidden;}
.related > a{vertical-align:top;width:calc(100% - 20px);max-width:340px;display:inline-block;text-align:center;margin:20px 10px;padding:25px;font-family:"Microsoft YaHei","宋体","Segoe UI","Lucida Grande",Helvetica,Arial,sans-serif,FreeSans,Arimo;}
.related a{display:inline-block;text-align:left;margin:20px auto;padding:10px 20px;opacity:0.8;-webkit-transition:opacity 0.3s;transition:opacity 0.3s;-webkit-backface-visibility:hidden;}
.related a:hover,.related a:active{opacity:1;}
.related a img{max-width:100%;opacity:0.8;border-radius:4px;}
.related a:hover img,.related a:active img{opacity:1;}
.related h3{font-family:"Microsoft YaHei",sans-serif;}
.related a h3{font-weight:300;margin-top:0.15em;color:#fff;}
/* icomoon */
.icon-zzsc-home-outline:before{content:"\e5000";}
.icon-zzsc-arrow-forward-outline:before{content:"\e5001";}
@media screen and (max-width:50em){.zzsc-header{padding:3em 10% 4em;}
.zzsc-header h1{font-size:2em;}
}
@media screen and (max-width:40em){.zzsc-header h1{font-size:1.5em;}
}
@media screen and (max-width:30em){.zzsc-header h1{font-size:1.2em;}
}