微信小程序封装transition 动画组件

2,555 阅读1分钟

要弄一个css3动画,首先要搞清楚4个状态,分别是enter enter-to leave leave-to即 开始前、到达目标、离开前、离开结束。并且对应有6个事件钩子before-enter enter after-enter before-leave leave after-leave大致流程如下:

有了基本状态,接着就是通过阶段性去修改对应的样式即可。

  • 基础样式:
.transition {
    -webkit-transition-duration: 300ms; transition-duration: 300ms;
    transition-timing-function: ease;
}
// 过渡属性 fade
.le-fade-enter-active,
.le-fade-leave-active {
  transition-property: opacity;
}
// 初始值 & 结束目标值
.le-fade-enter,
.le-fade-leave-to {
  opacity: 0;
}
  • 利用promise 去模拟状态变化过程
// 阶段类名
const getClassNames = function(moveName) {
  return {
    enter: `le-${moveName}-enter le-${moveName}-enter-active enter-class enter-active-class`,
    "enter-to": `le-${moveName}-enter-to le-${moveName}-enter-active enter-to-class enter-active-class`,
    leave: `le-${moveName}-leave le-${moveName}-leave-active leave-class leave-active-class`,
    "leave-to": `le-${moveName}-leave-to le-${moveName}-leave-active leave-to-class leave-active-class`
  };
};
// nextTick 事件模拟
const nextTick = () => new Promise(resolve => setTimeout(resolve, 1000 / 30));
methods: {
      enter() {
        const { duration, name } = this.data;
        const classNames = getClassNames(name);
        this.status = "enter";
        this.$emit("before-enter");
        // 过程模拟
        Promise.resolve()
          .then(nextTick)
          .then(() => {
            this.$emit("enter");
            this.setData({
              currClass: classNames.enter,
              display: true
            });
          })
          .then(nextTick)
          .then(() => {
            this.transitionEnded = false;
            // 微信动画结束时会回调onTransitionEnd  以下是为了兼容处理
            setTimeout(() => this.onTransitionEnd(), duration);
            this.setData({
              currClass: classNames["enter-to"]
            });
          })
          .catch(() => {});
      },
      leave() {
        if (!this.data.display) return false;
        const { duration, name } = this.data;
        const classNames = getClassNames(name);
        this.status = "leave";
        this.$emit("before-leave");
        Promise.resolve()
          .then(nextTick)
          .then(() => {
            this.$emit("leave");
            this.setData({
              currClass: classNames.leave
            });
          })
          .then(nextTick)
          .then(() => {
            this.transitionEnded = false;
            setTimeout(() => this.onTransitionEnd(), duration);
            this.setData({
              currClass: classNames["leave-to"]
            });
          });
      },
      onTransitionEnd() {
        // 兼容处理 小程序会回调
        if (this.transitionEnded) return;
        this.transitionEnded = true;
        this.$emit(`after-${this.status}`);
        const { show, display } = this.data;
        if (!show && display) {
          this.setData({ display: false });
        }
      }
}
  • 最后调整调整就ok 了