聊聊 transition 这个 CSS 属性

108 阅读1分钟

一、基于 height 实现动画(1)

当起始位置有一个 height 为 auto 时,不会有动画效果,因为 transition 这个属性需要起始位置的确切数值,才能计算出相应的动画。一般来说,设置 display: none 时,height 就为 auto。解决方法为:设置 height:0,同时,如果有子元素,还要设置 overflow:hidden。当然,在某些情况,也需要结合 opacity 这个属性来使用。最后,也不能用 visibility: hidden 来替代 display:none,因为前一个属性只是隐藏了元素,但位置还占着。下面是项目中的一些代码,仅供参考:

image.png
// html。简略结构。
<div>
  <div class="rigisterMain">注册</div>
  <div class="loginMain">登录</div>
  <button @click="switchComp($event)">切换组件</button>
</div>

// less。第一次加载页面时,隐藏创建账户组件。
.rigisterMain {
  height: 0;
  overflow: hidden; // 有子组件
}
.loginMain {
   overflow: hidden; // 提前设置默认值
 }

// vue.js
switchComp(e) {
  const rigisterEl = document.querySelector(".rigisterMain")
  const loginEl = document.querySelector(".loginMain")
  const rigisterHeight = getComputedStyle(rigisterEl, null)['height']
  const loginHeight = getComputedStyle(loginEl, null)['height']
  if (rigisterHeight === "0px" && e.target._prevClass === "rigisterTitle") {
    rigisterEl.style = `height:${loginHeight}; opacity:1`
    loginEl.style = `height:0px; opacity:0`
  } else if (loginHeight === "0px" && e.target._prevClass === "loginTitle") {
    loginEl.style = `height:${rigisterHeight}; opacity:1`
    rigisterEl.style = `height:0; opacity:0`
  }
},

二、基于 height 实现动画(2)

将元素的原始样式设置为 height:0; opacity:0; overflow: hiddern,然后再通过绑定 class 的方式,让元素隐藏或显示,并设置显示元素的样式 height:?px; opacity:1,最后,在对应的标签的上设置 transition 属性,即可实现动画效果。(关键还是要知道起始的高度,该方法优于第一种。

// html
<div>
  <div :class="{show: showRigister}">注册</div>
  <div :class="{show: showLogin}">登录</div>
  <button @click="switchComp($event)">切换组件</button>
</div>

// less
main {
   transition: height 1s ease-in-out;
   height: 0;
   overflow: hidden;
   opacity: 0;
   &.show {
      height: 151px;  // 高度是固定值,经计算得到。
      opacity: 1;
   }
}

// vue.js
data() {
  return {
    showRigister: false,
    showLogin: true
  }
},
methods: {
  switchComp(e) {
    if (e.target._prevClass === "rigisterTitle") {
      this.showRigister = true
      this.showLogin = false
    } else {
      this.showRigister = false
      this.showLogin = true
    }
  }
}

三、基于 opacity 和 transform 实现动画

这种方法主要是使用了 vue 里面的 Transition 组件,通过该组件,可以获取到 6 个 class,然后在里面设置 opacity | transform | transition | animation 等动画属性。值得注意的是,该组件必须结合 v-ifv-show 来使用,否则那 6 个 class 不会被添加到元素上。最后,这个组件无法对基于 height 来实现动画效果,因为使用 v-if 后,无初始高度,使用 v-show 后,初始高度为 auto

image.png

// html
<div>
  <transition name="fade1">
    <main v-show="showRigister">Rigister<main>
  </transition>
  <transition name="fade2">
    <main v-show="showLogin">Login<main>
  </transition>
  <button @click="switchComp($event)">切换组件</button>
</div>

// less
main{
  &.fade1-leave-to, &.fade2-leave-to {
    opacity: 0;
  }
  &.fade1-enter-to {
    opacity: 0.8;
  }
  &.fade2-enter-to {
    transform: translateY(-151px);
  }
  &.fade1-enter-active, &.fade2-enter-active,
  &.fade1-leave-active, &.fade2-leave-active {
    transition: all 1s ease;
  }
}

// vue.js
export default {
  data() {
    return {
      showRigister: false,
      showLogin: true
    }
  },
  methods: {
    switchComp(e) {
      if (e.target._prevClass === "rigisterTitle") {
        this.showRigister = true
        this.showLogin = false
      } else {
        this.showRigister = false
        this.showLogin = true
      }
    }
  }
}