简体   繁体   English

Vue 中大型交错列表的速度动画

[英]Velocity-animate for large staggered lists in Vue

I have a large list that I'm introducing velocity-animate into.我有一个很大的列表,我正在将速度动画引入其中。 At the moment, my test list has 59 individual items that a user can filter by search query (potentially could grow to hundreds of items).目前,我的测试列表有 59 个单独的项目,用户可以通过搜索查询过滤这些项目(可能会增长到数百个项目)。 I am animating currently according to the way the Vue docs show it being done, but of course their list only has a few items.我目前正在根据Vue 文档显示的方式制作动画,但当然他们的列表只有几个项目。

In my app, it takes several seconds for the animation to finish which is definitely not ideal.在我的应用程序中,动画需要几秒钟才能完成,这绝对不理想。 Is there any way of "batch" animating?有没有“批量”动画的方法? I think ideally what would happen is I would debounce the input so that only after a second or two, will the search actually perform.我认为理想情况下会发生什么是我会对输入进行去抖动,这样只有在一两秒后,搜索才会真正执行。 Then in the method, the items are filtered, and all of the items that aren't a match disappear.然后在该方法中,过滤项目,所有不匹配的项目都消失了。 How can I accomplish this?我怎样才能做到这一点?

<template>
  <v-text-field
    background-color="#fff"
    clearable
    dense
    flat
    hide-details
    label="Search"
    placeholder="Search"
    solo-inverted
    :value="searchQuery"
    @click:append="clearSearch"
    @input="debounceSearchQuery" />
  <v-list>
    <v-list-item-group>
      <draggable
        class="drag-area list-group"
        :group="{ name: 'items', pull: 'clone', put: false}"
        handle=".gear-handle"
        :list="filteredItems"
        :sort="false"
        @change="log">
          <transition-group
            :css="false"
            name="staggered-fade"
            @before-enter="beforeEnter"
            @enter="enter"
            @leave="leave">
            <v-list-item
              v-for="(item, i) in filteredItems"
              :key="item.id"
              :data-index="i">
              <p class="mb-0 white--text">
                {{ item.name }}
              </p>
            </v-list-item>
          </transition-group>
        </draggable>
      </v-list-item-group>
    </v-list>
</template>

export default {
  data: () => ({
    searchQuery: ''
  }),

  computed: {
    filteredItems () {
      const filteredItems = [];
      this.categories.forEach(category => {
        if (this.searchQuery) {
          const text = this.searchQuery.toLowerCase();
          filteredItems.push(category.items.filter(item => item.name && item.name.toLowerCase().includes(text)));
        } else {
          filteredItems.push(category.items);
        }
      });
      return filteredItems.flat();
    },
  },

  methods: {
  // gsap methods //
    beforeEnter (el) {
      el.style.opacity = 0;
      el.style.height = 0;
    },
    enter (el, done) {
      const delay = el.dataset.index * 150;
      setTimeout(() => {
        this.$velocity(
          el,
          { opacity: 1, height: '1.6em', duration: 50 },
          [0.57, 0.06, 0, 1.06],
          { complete: done }
        );
      }, delay);
    },
    leave (el, done) {
      const delay = el.dataset.index * 150;
      setTimeout(() => {
        this.$velocity(
          el,
          { opacity: 0, height: 0 },
          { complete: done }
        );
      }, delay);
    },
    // end gsap methods
    debounceSearchQuery: debounce(function (e) {
      this.searchQuery = e;
    }, 1000)
  }
}

I think "staggering" animation and "batch" running transitions are more like two different things—it's almost like you can't have your cake and eat it too.我认为“惊人”动画和“批量”运行过渡更像是两种不同的东西——就像你不能吃蛋糕一样。

Nonetheless, if you are simply after smooth, sliding transitions that kind of have staggering effect, you could actually do that with <transition-group> + CSS only (no transition hooks necessary).尽管如此,如果你只是追求平滑的、具有惊人效果的滑动过渡,你实际上可以只使用<transition-group> + CSS 来做到这一点(不需要过渡钩子)。 Here's a quick example (click "Run" and then "Full-page" for better view):这是一个简单的示例(单击“运行”,然后单击“整页”以获得更好的视图):

 new Vue({ vuetify: new Vuetify({ theme: { dark: true } }), data: () => ({ searchQuery: '', categories: [ { items: [{ name: 'vue.js', id: 1 }] }, { items: [{ name: 'react.js', id: 2 }] }, { items: [{ name: 'angular.js', id: 3 }] }, { items: [{ name: 'velocity-animate', id: 4 }] }, { items: [{ name: 'lodash', id: 5 }] }, { items: [{ name: 'debounce', id: 6 }] }, ] }), computed: { filteredItems() { const filteredItems = []; const text = this.searchQuery.toLowerCase(); this.categories.forEach(category => { if (this.searchQuery) { filteredItems.push(category.items.filter(item => item.name && item.name && item.name.toLowerCase().includes(text))); } else { filteredItems.push(category.items); } }); return filteredItems.flat(); }, }, methods: { debounceSearchQuery: _.debounce(function(e) { this.searchQuery = e; }, 200), clearSearch() { this.searchQuery = ''; } } }).$mount('#app');
 .staggered-fade-item { transition-timing-function: cubic-bezier(0.57, 0.06, 0, 1.06); transition-duration: 500ms; transition-property: opacity, transform; } .staggered-fade-enter, .staggered-fade-leave-to { opacity: 0; transform: translateY(-30px); }
 <script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script> <script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js"></script> <link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet"> <div id="app"> <v-app> <v-main> <v-container> <v-text-field @click:append="clearSearch" @input="debounceSearchQuery" :value="searchQuery" label="Search" placeholder="Search" autocomplete="off" solo-inverted clearable dense flat hide-details autofocus dark> </v-text-field> <v-list> <transition-group name="staggered-fade" tag="v-list-item-group"> <v-list-item v-for="item in filteredItems" :key="item.id" class="staggered-fade-item"> <p class="mb-0 white--text"> {{ item.name }} </p> </v-list-item> </transition-group> </v-list> </v-container> </v-main> </v-app> </div>

Another recommendation would be Velocity UI pack .另一个建议是Velocity UI pack This add-on allows you to do sequence running and it comes with some pre-registered effects, which are great for staggering effects.这个附加组件允许您进行序列运行,它带有一些预先注册的效果,非常适合惊人的效果。 (Check out the docs for more transition effects). (查看文档了解更多过渡效果)。 🙂 🙂

 new Vue({ vuetify: new Vuetify({ theme: { dark: true } }), data: () => ({ searchQuery: '', categories: [ { items: [{ name: 'vue.js', id: 1 }] }, { items: [{ name: 'react.js', id: 2 }] }, { items: [{ name: 'angular.js', id: 3 }] }, { items: [{ name: 'velocity-animate', id: 4 }] }, { items: [{ name: 'lodash', id: 5 }] }, { items: [{ name: 'debounce', id: 6 }] }, ] }), computed: { filteredItems() { const filteredItems = []; const text = this.searchQuery.toLowerCase(); this.categories.forEach(category => { if (this.searchQuery) { filteredItems.push(category.items.filter(item => item.name && item.name && item.name.toLowerCase().includes(text))); } else { filteredItems.push(category.items); } }); return filteredItems.flat(); }, }, methods: { debounceSearchQuery: _.debounce(function(e) { this.searchQuery = e; }, 200), clearSearch() { this.searchQuery = ''; } }, watch: { filteredItems() { Velocity( this.$refs.items.map(vnode => vnode.$el), 'transition.flipYIn', { stagger: 100, drag: true } ); } } }).$mount('#app');
 <script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script> <script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script> <script src="https://cdn.jsdelivr.net/npm/velocity-animate@1.5.2/velocity.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/velocity-animate@1.5.2/velocity.ui.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js"></script> <link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet"> <div id="app"> <v-app> <v-main> <v-container> <v-text-field @click:append="clearSearch" @input="debounceSearchQuery" :value="searchQuery" label="Search" placeholder="Search" autocomplete="off" solo-inverted clearable dense flat hide-details autofocus dark> </v-text-field> <v-list> <v-list-item-group> <v-list-item v-for="item in filteredItems" :key="item.id" ref="items"> <p class="mb-0 white--text"> {{ item.name }} </p> </v-list-item> </v-list-item-group> </v-list> </v-container> </v-main> </v-app> </div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM