移動端重構實戰系列4——進入離開動畫

進入離開動畫

在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

es6 封裝動畫進入離開類

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

出處:http://www.w3cplus.com/mobile/sandal-parts-4.html函數

相關文章
相關標籤/搜索