提交按钮动画效果(基于SVGi)

来源:互联网 发布:网络新词及意思和出处 编辑:程序博客网 时间:2024/04/19 20:47

翻译整理一篇外文前端效果,基于SVG的按钮动画。

效果预览

效果:

1、hover:按钮颜色过渡;
2、click:按钮转换为圆环,开始环形描边动画;
3、完成环形描边动画,显示成功或错误状态 (对勾和差);
4、恢复初始按钮状态

虽然存在其他可选方案,但本文将主要通过基于SVG和CSS transition技术实现这一效果。基于SVG的动画可能不会被所有浏览器支持,可视本文为前端实验性案例。

按钮状态:


Html代码段:

<div id="progress-button" class="progress-button"><!-- button元素,显示button初始状态--><button><span>Submit</span></button><!-- svg 圆形图案,通过path元素进行描边动画 --><svg class="progress-circle" width="70" height="70"><path d="m35,2.5c17.955803,0 32.5,14.544199 32.5,32.5c0,17.955803 -14.544197,32.5 -32.5,32.5c-17.955803,0 -32.5,-14.544197 -32.5,-32.5c0,-17.955801 14.544197,-32.5 32.5,-32.5z"/></svg><!-- 提交成功的显示状态 --><svg class="checkmark" width="70" height="70"><path d="m31.5,46.5l15.3,-23.2"/><path d="m31.5,46.5l-8.5,-7.1"/></svg><!-- 提交失败的显示状态-->  <svg class="cross" width="70" height="70"><path d="m35,35l-9.3,-9.3"/><path d="m35,35l9.3,9.3"/><path d="m35,35l-9.3,9.3"/><path d="m35,35l9.3,-9.3"/>  </svg></div>


CSS代码段:


.progress-button {  position: relative;         display: inline-block; text-align: center;width: 45%;min-width: 250px;margin: 10px;}.progress-button button {    display: block;    margin: 0 auto;    padding: 0;    width: 250px;    height: 70px;    border: 2px solid #1ECD97;    border-radius: 35px;    background: transparent;    color: #1ECD97;    letter-spacing: 1px;    font-size: 18px;    font-family: 'Montserrat', sans-serif;    /* button元素过渡效果应用属性:背景色,前景色,宽度,边框宽,边框颜色 */    -webkit-transition: background-color 0.3s, color 0.3s, width 0.3s, border-width 0.3s, border-color 0.3s;    -moz-transition: background-color 0.3s, color 0.3s, width 0.3s, border-width 0.3s, border-color 0.3s;    -o-transition: background-color 0.3s, color 0.3s, width 0.3s, border-width 0.3s, border-color 0.3s;    transition: background-color 0.3s, color 0.3s, width 0.3s, border-width 0.3s, border-color 0.3s;}.progress-button button:hover { /*鼠标移入改变背景色和前景色,实现淡入淡出效果*/     background-color: #1ECD97;     color: #fff;     cursor:pointer;    }.progress-button svg {    position: absolute;    top: 0;    left: 50%;    -webkit-transform: translateX(-50%);    transform: translateX(-50%);    pointer-events: none;}.progress-button svg path {/*隐藏svg path元素*/        opacity:0;    fill:none;}.progress-button svg.progress-circle path {    stroke: #1ECD97;    stroke-width: 5;}.progress-button svg.checkmark path, .progress-button svg.cross path {    stroke:#fff;    stroke-linecap:round;    stroke-width:4px;    -webkit-transition:opacity 0.1s;    transition:opacity 0.1s;    }.loading.progress-button button {    width: 70px; /* make a circle */    border-width: 5px;    border-color: #ddd;    background-color: transparent;    color: #fff;}.loading.progress-button span {    -webkit-transition: opacity 0.15s;    transition: opacity 0.15s;}.loading.progress-button span,.success.progress-button span,.error.progress-button span {    opacity: 0; /*在整个动画过程中,隐藏button span元素*/}.progress-button button span {    -webkit-transition: opacity 0.3s 0.1s;    transition: opacity 0.3s 0.1s;}.success.progress-button button,.error.progress-button button {    -webkit-transition: background-color 0.3s, width 0.3s, border-width 0.3s;    transition: background-color 0.3s, width 0.3s, border-width 0.3s;}.loading.progress-button svg.progress-circle path,.success.progress-button svg.checkmark path,.error.progress-button svg.cross path {    opacity: 1;    -webkit-transition: stroke-dashoffset 0.3s;/*改变svg path元素的stroke-dashoffeset的属性实现动画*/    transition: stroke-dashoffset 0.3s;}.success.progress-button button {    border-color: #1ECD97;    background-color: #1ECD97;} .error.progress-button button {    border-color: #FB797E;    background-color: #FB797E;}.elastic.progress-button button {    -webkit-transition: background-color 0.3s, color 0.3s, width 0.3s cubic-bezier(0.25, 0.25, 0.4, 1.6), border-width 0.3s, border-color 0.3s;    -webkit-transition: background-color 0.3s, color 0.3s, width 0.3s cubic-bezier(0.25, 0.25, 0.4, 1.6), border-width 0.3s, border-color 0.3s;    transition: background-color 0.3s, color 0.3s, width 0.3s cubic-bezier(0.25, 0.25, 0.4, 1.6), border-width 0.3s, border-color 0.3s;} .loading.elastic.progress-button button {    -webkit-transition: background-color 0.3s, color 0.3s, width 0.3s cubic-bezier(0.6, 0, 0.75, 0.75), border-width 0.3s, border-color 0.3s;    -webkit-transition: background-color 0.3s, color 0.3s, width 0.3s cubic-bezier(0.6, -0.6, 0.75, 0.75), border-width 0.3s, border-color 0.3s;    transition: background-color 0.3s, color 0.3s, width 0.3s cubic-bezier(0.6, -0.6, 0.75, 0.75), border-width 0.3s, border-color 0.3s;}

javascript代码段:

依赖库:Modernizr.js(自定义下载,主要用于判断浏览器对transition的支持);classie.js(判断元素应用了样式,为元素添加、删除样式,或进行样式切换)。

html内嵌javascript代码:

<script>  [].slice.call(document.querySelectorAll('.progress-button')).forEach(function(btn,pos){  new ProgressButton(btn,{  callback:function(instance){ var progress=0; var interval=setInterval(function(){ progress=Math.min(progress+Math.random()*0.1,1); instance.setProgress(progress); if(progress===1){ instance.stop(pos===1 || pos ===3?-1:1); clearInterval(interval); }  },150);  }  });  });    </script>


外部js:

(function(window){var transEndEventNames={'WebkitTransition': 'webkitTransitionEnd','MozTransition': 'transitionend','OTransition': 'oTransitionEnd','msTransition': 'MSTransitionEnd','transition': 'transitionend'};var transEndEventName=transEndEventNames[Modernizr.prefixed( 'transition' ) ];var support={transitions:Modernizr.csstransitions};function extend( a, b ) {for( var key in b ) { if( b.hasOwnProperty( key ) ) {a[key] = b[key];}}return a;}function SVGEL(el){//SVG 元素的构造函数//alert(el);this.el = el;this.paths = [].slice.call( this.el.querySelectorAll( 'path' ) );this.pathsArr = new Array();this.lengthsArr = new Array();this._init();}SVGEL.prototype._init=function(){var self = this;this.paths.forEach( function( path, i ) {self.pathsArr[i] = path;path.style.strokeDasharray = self.lengthsArr[i] = path.getTotalLength();} );this.draw(0);};SVGEL.prototype.draw=function(value){for( var i = 0, len = this.pathsArr.length; i < len; ++i ){this.pathsArr[i].style.strokeDashoffset = this.lengthsArr[i] * ( 1 - value );}};function ProgressButton(element,options){//ProgressButton类的构造函数入口this.element=element;this.options = extend( {}, this.options );extend( this.options, options );this._init();}ProgressButton.prototype._init=function(){//ProgessButton类的_init实例方法,用于初始化。this.button = this.element.querySelector( 'button' );this.progressElement = new SVGEL( this.element.querySelector( 'svg.progress-circle' ) );this.successElement= new SVGEL( this.element.querySelector( 'svg.checkmark' ) );this.errorElement = new SVGEL( this.element.querySelector( 'svg.cross' ) );this._initEvents();this._enable();};ProgressButton.prototype.options={statusTime : 1500};ProgressButton.prototype._initEvents=function(){var self=this;this.button.addEventListener("click",function(){ self._submit();});};ProgressButton.prototype._submit=function(){classie.addClass( this.element, 'loading' );var self=this;var onEndBtnTransitionFn=function(event){if(support.transitions){if(event.propertyName!=='width'){return false;}this.removeEventListener(transEndEventName,onEndBtnTransitionFn);}this.setAttribute('disabled','');if(typeof self.options.callback==='function'){self.options.callback(self);}else{self.setProgress(1);self.stop();}};if(support.transitions){this.button.addEventListener(transEndEventName,onEndBtnTransitionFn);}else{onEndBtnTransitionFn();}};ProgressButton.prototype.stop=function(status){var self=this;var endloading=function(){self.progressElement.draw(0);if(typeof status==='number'){var statusClass=status>=0?'success':'error';var statusElement=status>=0?self.successElement:self.errorElement;statusElement.draw(1);classie.addClass( self.element, statusClass );setTimeout(function(){classie.removeClass(self.element,statusClass);statusElement.draw(0);self._enable();},self.options.statusTime);}else{self._enable();}classie.removeClass(self.element,'loading');};setTimeout(endloading,300);};ProgressButton.prototype.setProgress=function(val){this.progressElement.draw(val);};ProgressButton.prototype._enable=function(){this.button.removeAttribute('disabled');};window.ProgressButton=ProgressButton;//将ProgressButton类附加到window对象上,便于外部调用})(window);


0 0
原创粉丝点击