vue动画move的实现

<transition-group> 组件还有一个特殊之处。不仅可以进入和离开动画,还可以改变定位。要使用这个新功能只需了解新增的 v-move class,它会在元素的改变定位的过程中应用。像之前的类名一样,可以通过 name attribute 来自定义前缀,也可以通过 move-class attribute 手动设置。

v-move 对于设置过渡的切换时机和过渡曲线非常有用,你会看到如下的例子:

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.1/lodash.min.js"></script>

<div id="flip-list-demo" class="demo">
  <button v-on:click="shuffle">Shuffle</button>
  <transition-group name="flip-list" tag="ul">
    <li v-for="item in items" v-bind:key="item">
      {{ item }}
    </li>
  </transition-group>
</div>
new Vue({
  el: '#flip-list-demo',
  data: {
    items: [1,2,3,4,5,6,7,8,9]
  },
  methods: {
    shuffle: function () {
      this.items = _.shuffle(this.items)//乱序函数
    }
  }
})
.flip-list-move {
  transition: transform 1s;
}
  • 3
  • 1
  • 8
  • 6
  • 9
  • 4
  • 5
  • 7
  • 2

这个看起来很神奇,内部的实现,Vue 使用了一个叫 FLIP 简单的动画队列
使用 transforms 将元素从之前的位置平滑过渡新的位置。

该动画的思路是:

1.标记处未变化前的位置(用getBoundingClientReact);

2.不用动画,立即让元素移动到目标位置,并标记出来变化后的位置;

3.重新移动到原位置,让元素移动到原来的位置;

4动画过渡到新位置;

具体的例子,AB两个元素的交换位置为例

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <button>change</button>
  <li>A</li>
  <li>B</li>
  <script>
    var btn = document.getElementsByTagName('button')[0];


    function getTop(dom) {
      return dom.getBoundingClientRect().top;
    }

    function animate(dom, initTop) {
      var char = initTop - getTop(dom); //获取两个位置的差值
      dom.style.transform = `translateY(${char}px)`; //立即变到原来的位置

      requestAnimationFrame(() => {
        requestAnimationFrame(() => { //requestanimationframe是在渲染前执行,所以需要两次后
          dom.style.transform = null;
          dom.style.transition = dom.style.transition = '1s';
          dom.addEventListener('transitionend', function () {
            dom.style.transition = null;
          })
        })
      })
    }
    btn.onclick = function () {
      var li_1 = document.getElementsByTagName('li')[0];
      var li_2 = document.getElementsByTagName('li')[1];
      var li_1_top = getTop(li_1);
      var li_2_top = getTop(li_2);
      document.body.insertBefore(li_2, li_1);

      animate(li_1, li_1_top);
      animate(li_2, li_2_top)
    }



  </script>
</body>

</html>

 

posted @ 2021-06-30 12:31  当当和瓶瓶  阅读(755)  评论(0编辑  收藏  举报