我在nuxt组件中制作滚动触发动画时遇到了一些麻烦.

基本上,我有一个用于nuxt页面的lenis脚本,并且在该页面内有一个用于projectIt.vue组件的滚动触发器脚本.我通过nPM安装了gsap,并将其导入页面和组件中.

该代码似乎有效,因为我们输入了onEnter()回调,但根本没有动画.

<script>
import { gsap } from "gsap";
import ScrollTrigger from 'gsap/ScrollTrigger';

export default {

  mounted() {
    gsap.registerPlugin(ScrollTrigger);
    const trigger = this.$refs.animtrigger; 
    console.log(trigger);
    gsap.to(trigger, {
      scrollTrigger: {
        trigger: trigger, 
        start: 'top center', 
        y: '-=100px', 
        ease: "power1.inOut",
        stagger: .2,
        onEnter: () => {
          console.log('coucou')
        }
      }
    })
  },

  props: {
  titre: String,
  type: String,
  composition: Array,
  outils: Array,
  date: String,
  image: String,
  alt: String
  }

}

</script>

<template>
  <div class="projectItem" ref="animtrigger">
    <div class="column">
      <div class="column-c-image">
        <img :src="(image)" :alt="(alt)" class="image">
      </div>
      <div class="column-c-content">
        <p>{{titre}}</p>
      <svg class="arrow" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
        <path d="M6.22438 17.9287C6.36591 18.0667 6.55676 18.1423 6.75438 18.1387C6.95141 18.1391 7.14109 18.064 7.28438 17.9287L16.6144 8.58994V16.6487C16.6144 17.0629 16.9502 17.3987 17.3644 17.3987C17.5658 17.4042 17.7608 17.3273 17.9042 17.1857C18.0477 17.0442 18.1272 16.8502 18.1244 16.6487V6.9165C18.1504 6.80241 18.1498 6.68188 18.1198 6.56444C18.0519 6.29871 17.8444 6.09121 17.5787 6.02334C17.4612 5.99335 17.3407 5.99275 17.2266 6.01873H7.49438C7.08017 6.01873 6.74438 6.35451 6.74438 6.76873C6.74438 7.18294 7.08017 7.51873 7.49438 7.51873H15.5644L6.22438 16.8587C6.08085 16.9997 6 17.1925 6 17.3937C6 17.5949 6.08085 17.7877 6.22438 17.9287Z" fill="black"/>
      </svg>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">

@use "~/assets/css/main.scss";
  .projectItem {
    width: 628px;

    .column {
      display: flex;
      flex-direction: column;
      gap: .2rem;

      .column-c-image {
        object-fit: cover;

        .image {
          width: 100%;
          height: 700px;
          object-fit: cover;
          border-radius: 1rem;

        }
      }

      .column-c-content {
        display: flex;
        flex-direction: row;
        justify-content: space-between;
        align-items: center;
        width: 100%;
      }
    }
  }


</style>



谢谢!

推荐答案

如果您需要加载多个这样的图像,建议使用gsap.timeline().

const timeline = gsap.timeline({
  scrollTrigger: {
    start: 'top center', 
    toggleActions: "play none none reverse",
  },
  stagger: {
    each: 0.2,
    from: 'left',
  },
});

timeline.from(trigger, {
  y: -100,
  opacity: 0,
  ease: "power1.inOut",
});

由于GSAP不是基于Vue的,因此您不必坚持传递Vue元素.如果您确定多姆已加载(可以在mounted()挂钩中假设),则您也可以将原生JS Select 器传递给to()函数,因为这只会导致一个动画.要在多个动画之间插入延迟,您需要将许多元素传递给一个动画.

gsap.registerPlugin(ScrollTrigger);

gsap.to('.projectItem', {
  scrollTrigger: {
    start: 'top center',
    toggleActions: "play none none reverse",
  },
  y: -100,
  opacity: 1,
  ease: "power1.inOut",
  stagger: {
    each: 0.2,
    from: 'left',
  },
});

我做了一个内联CDO示例.当图像进入可见区域时,它就会出现,当它离开可见区域时,它就会消失.

例#1

const { createApp } = Vue;

const GsapExample = {
  props: {
    titre: String,
    type: String,
    composition: Array,
    outils: Array,
    date: String,
    image: String,
    alt: String,
  },
  template: `
    <div class="projectItem" ref="animtrigger">
      <div class="column">
        <div class="column-c-image">
          <img :src="(image)" :alt="(alt)" class="image">
        </div>
        <div class="column-c-content">
          <p>{{ titre }}</p>
        <svg class="arrow" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
          <path d="M6.22438 17.9287C6.36591 18.0667 6.55676 18.1423 6.75438 18.1387C6.95141 18.1391 7.14109 18.064 7.28438 17.9287L16.6144 8.58994V16.6487C16.6144 17.0629 16.9502 17.3987 17.3644 17.3987C17.5658 17.4042 17.7608 17.3273 17.9042 17.1857C18.0477 17.0442 18.1272 16.8502 18.1244 16.6487V6.9165C18.1504 6.80241 18.1498 6.68188 18.1198 6.56444C18.0519 6.29871 17.8444 6.09121 17.5787 6.02334C17.4612 5.99335 17.3407 5.99275 17.2266 6.01873H7.49438C7.08017 6.01873 6.74438 6.35451 6.74438 6.76873C6.74438 7.18294 7.08017 7.51873 7.49438 7.51873H15.5644L6.22438 16.8587C6.08085 16.9997 6 17.1925 6 17.3937C6 17.5949 6.08085 17.7877 6.22438 17.9287Z" fill="black"/>
        </svg>
        </div>
      </div>
    </div>
  `,
};
  
const app = createApp({
  components: {
    GsapExample,
  },
  mounted() {
    gsap.registerPlugin(ScrollTrigger);

    gsap.to('.projectItem', {
      scrollTrigger: {
        start: 'top center',
        toggleActions: "play none none reverse",
      },
      y: -100,
      opacity: 1,
      ease: "power1.inOut",
      stagger: {
        each: 0.2,
        from: 'left',
      },
    });
  },
}).mount('#app');
.container {
  margin-top: 300px; /* no need it, just added it for testing the appearance and disappearance */
  display: flex;
  flex-wrap: wrap;
  gap: 50px;
}

.projectItem {
  width: 200px;
  opacity: 0;
}

.projectItem .column {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.projectItem .column .column-c-image {
  object-fit: cover;
}

.projectItem .column .column-c-image .image {
  width: 100%;
  height: 200px;
  object-fit: cover;
  border-radius: 1rem;
}

.projectItem .column .column-c-content {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  width: 100%;
}
<script src="https://unpkg.com/vue@3.4/dist/vue.global.prod.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js"></script>

<div id="app">
  <div class="container">
    <gsap-example
      v-for="number of [1, 2, 3, 4, 5, 6, 7, 8, 9]"
      titre="Title"
      type="Type"
      :composition="['Composition1', 'Composition2']"
      :outils="['Tool1', 'Tool2']"
      date="2024-04-24"
      :image="`https://picsum.photos/200/200?${number}`"
      alt="Image Alt"
    />
  </div>
</div>

例#2

const { createApp } = Vue;

const GsapExample = {
  props: {
    titre: String,
    type: String,
    composition: Array,
    outils: Array,
    date: String,
    image: String,
    alt: String,
  },
  template: `
    <div class="projectItem" ref="animtrigger">
      <div class="column">
        <div class="column-c-image">
          <img :src="(image)" :alt="(alt)" class="image">
        </div>
        <div class="column-c-content">
          <p>{{ titre }}</p>
        <svg class="arrow" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
          <path d="M6.22438 17.9287C6.36591 18.0667 6.55676 18.1423 6.75438 18.1387C6.95141 18.1391 7.14109 18.064 7.28438 17.9287L16.6144 8.58994V16.6487C16.6144 17.0629 16.9502 17.3987 17.3644 17.3987C17.5658 17.4042 17.7608 17.3273 17.9042 17.1857C18.0477 17.0442 18.1272 16.8502 18.1244 16.6487V6.9165C18.1504 6.80241 18.1498 6.68188 18.1198 6.56444C18.0519 6.29871 17.8444 6.09121 17.5787 6.02334C17.4612 5.99335 17.3407 5.99275 17.2266 6.01873H7.49438C7.08017 6.01873 6.74438 6.35451 6.74438 6.76873C6.74438 7.18294 7.08017 7.51873 7.49438 7.51873H15.5644L6.22438 16.8587C6.08085 16.9997 6 17.1925 6 17.3937C6 17.5949 6.08085 17.7877 6.22438 17.9287Z" fill="black"/>
        </svg>
        </div>
      </div>
    </div>
  `,
};
  
const app = createApp({
  components: {
    GsapExample,
  },
  mounted() {
    gsap.registerPlugin(ScrollTrigger);
    
    // only need to create the timeline once
    const timeline = gsap.timeline({
      scrollTrigger: {
        start: 'top center', 
        toggleActions: "play none none reverse",
      },
      stagger: {
        each: 0.2,
        from: 'left',
      },
    });

    const triggers = document.querySelectorAll('.projectItem');
    triggers.forEach((trigger, index) => {
      timeline.from(trigger, {
        y: -100,
        opacity: 0,
        ease: "power1.inOut",
      });
    });
  },
}).mount('#app');
.container {
  margin-top: 300px; /* no need it, just added it for testing the appearance and disappearance */
  display: flex;
  flex-wrap: wrap;
  gap: 50px;
}

.projectItem {
  width: 200px;
}

.projectItem .column {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.projectItem .column .column-c-image {
  object-fit: cover;
}

.projectItem .column .column-c-image .image {
  width: 100%;
  height: 200px;
  object-fit: cover;
  border-radius: 1rem;
}

.projectItem .column .column-c-content {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  width: 100%;
}
<script src="https://unpkg.com/vue@3.4/dist/vue.global.prod.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js"></script>

<div id="app">
  <div class="container">
    <gsap-example
      v-for="number of [1, 2, 3, 4, 5, 6, 7, 8, 9]"
      titre="Title"
      type="Type"
      :composition="['Composition1', 'Composition2']"
      :outils="['Tool1', 'Tool2']"
      date="2024-04-24"
      :image="`https://picsum.photos/200/200?${number}`"
      alt="Image Alt"
    />
  </div>
</div>

Vue.js相关问答推荐

将事件监听器绑定到动态元素

Vue.js编译的render函数不起作用

带有 netlify.toml 文件的环境变量

如何将字符串中的
解析为 VUE.js 中的 html 标记

更改 Vuetify 轮播高度

Webpack 导入的模块不是函数

我可以在未注册的组件上构建 Vue.js 失败吗?

在 vuejs 中显示两个组件,但只显示一个,为什么?

如何在 vuejs 自定义指令中传递动态参数

避免在运行时向 Vue 实例或其根 $data 添加响应式属性

使用 aria-live 在 vue.js 中向屏幕阅读器宣布信息

全局方法和实例方法有什么区别?

将数据传递给另一条路由上的组件

vue js 中的 process.env.BASE_URL 是什么?

在 .vue 文件中使用 Vue.set() 和 Vue.use()

克隆元素并附加到 DOM 的正确方法

升级到 vue-cli 3 后,HTML 中的空格消失了

如何在 vuejs 中的基于类的组件中编写计算设置器

使用 svelte js 的原因

如何在 vue 组件中使用 vuex?