在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();