在sandal的_animation.scss
中咱们定义了fade-in/out
, shrink-in/out
, up-in/out
, down-in/out
, left-in/out
, right-in/out
六组基础动画,下面咱们以fade-in/out
为例说明如何使用:css
直接调用mixin:html
@include animation-fade-in;
@include animation-fade-out;
编译出的CSS为:node
.fade-in, .fade-out { -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; } .fade-in { -webkit-animation-name: fadeIn; animation-name: fadeIn; } @-webkit-keyframes fadeIn { 0% { opacity: 0; } 100% { opacity: 1; } } @keyframes fadeIn { 0% { opacity: 0; } 100% { opacity: 1; } } .fade-out { -webkit-animation-name: fadeOut; animation-name: fadeOut; } @-webkit-keyframes fadeOut { 0% { opacity: 1; } 100% { opacity: 0; } } @keyframes fadeOut { 0% { opacity: 1; } 100% { opacity: 0; } }
固然为了扩展,mixin还定义了两个参数:animation-fade-in($className: fade, $from: 0)
,animation-fade-out($className: fade, $to: 0)
,第一个表示要用的class名字(会自动补上in/out
),第二个表示opacity
值(from
为起始,to
为结束)es6
如今CSS的动画class已经有了,接下来就是用JS把这两个class分别添加到进入和离开的时候。web
export class AnimateInOut { constructor({ele, className, inCallback, outCallback}) { this.ele = ele.nodeType === 1 ? ele : document.querySelector(ele); this.inClass = className + '-in'; // 加上in表示进入class this.outClass = className + '-out'; // 加上out表示离开class this.inCallback = inCallback; // 进入动画结束后回调函数 this.outCallback = outCallback; // 离开动画结束后回调函数 this.animationend = this.whichEndEvent(); // 使用animationend事件 this.endBind = this.end.bind(this); // 绑定this } // 进入 enter() { this.ele.classList.add(this.inClass); // animation动画结束以后,移除该class this.ele.addEventListener(this.animationend, this.endBind); } // 离开 leave() { this.ele.classList.add(this.outClass); // animation动画结束以后,移除该class this.ele.addEventListener(this.animationend, this.endBind); } // 动画结束事件处理函数 end() { var ele = this.ele, eleClassList = ele.classList, isIn = eleClassList.contains(this.inClass), // 进入 isOut = eleClassList.contains(this.outClass); // 离开 ele.removeEventListener(this.animationend, this.endBind); if(isIn) { eleClassList.remove(this.inClass); this.inCallback && this.inCallback(); } if(isOut) { eleClassList.remove(this.outClass); this.outCallback && this.outCallback(); } } // 判断end事件,可独立为一个基础功能 whichEndEvent() { var k el = document.createElement('div'); var animations = { "animation" : "animationend", "WebkitAnimation": "webkitAnimationEnd" } for(k in animations) { if(el.style[k] !== undefined) { return animations[k]; } } } }
注意这里咱们采用的animation
动画,而不是transition
动画,由于transition动画从none到block的时候,直接添加动画的class是不会有动画效果的(除非使用回调函数或promise),而animation动画从none到block的时候添加动画class是能够的。这里不想设计得太复杂,因此直接使用animation动画promise
function leaveEnd() { console.log('hello the world'); } var animateInOut = new AnimateInOut({ele: $el, className: 'fade', outCallback: leaveEnd}); // 进入的时候调用 animateInOut.enter(); // 离开的时候调用 animateInOut.leave();