janpaepke / ScrollMagic

The javascript library for magical scroll interactions.
http://ScrollMagic.io
Other
14.88k stars 2.17k forks source link

How to use ScrollMagic with vue nuxt #947

Open okrymus opened 4 years ago

okrymus commented 4 years ago

I have no idea how to use ScrollMagic with vue nuxt. If any one know how to, thank you in advance

slecorvaisier commented 4 years ago

Hi there. If it can help you or someone else, here is how I implemented it with Nuxtjs (static generation):

In nuxt,config.js, I add all the necessary dependencies in the header tag:

script: [
      { src: "//cdnjs.cloudflare.com/ajax/libs/gsap/3.2.6/gsap.min.js" },
      { src: "//cdnjs.cloudflare.com/ajax/libs/gsap/3.2.6/ScrollToPlugin.min.js" },
      { src: "//cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.7/ScrollMagic.min.js" },
      { src: "//cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.7/plugins/animation.gsap.js" },
      process.env.NODE_ENV !== "production" ? { src: "//cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.7/plugins/debug.addIndicators.min.js" } : {}
    ]

As I use the same animations in different places and components, I moved the scene creation in a mixin mixins/AnimationMixins.js:

const REVEAL_DURATION = 1.75;

export default {
  methods: {
    revealOnScroll(trigger, selector = null) {

      // build a tween with gsap
      const tw = gsap.from(selector || trigger, {
        duration: REVEAL_DURATION,
        ease: "power2.inOut",
        opacity: 0
      });

      // init the scene and add the tween to it
      const scene = new ScrollMagic.Scene({
        triggerElement: trigger,
        triggerHook: "onCenter",
        reverse: false
      })
        .setTween(tw);

      // when in development, add indicators
      if (process.env !== "production") {
        scene.addIndicators();
      }

      // add scene to controller, more on this later
      this.$root.$emit("addScene", scene);
    }
  }
};

My main and unique controller is located in my layouts/default.vue file, in the mounted hook:

mounted() {
    // init scollmagic controller
    this.controller = new ScrollMagic.Controller();

    // listen for scene addition
    this.$root.$on("addScene", scene => {
      this.controller.addScene(scene);
    });
}

And finally, set an animation inside a component, wherever it is located.

<template>
  <div id="my-component">
     <div>some content</div>
  </div>
</template>

<script>
import AnimationMixins from "@/mixins/AnimationMixins";

export default {
  name: "MyComponent",
  mixins: [AnimationMixins],
  async mounted() {
    await this.$nextTick();

    this.revealOnScroll("#my-component");
  }
};
</script>

My main issue has been to be able to add scenes while the controller was not in the same component. My solution to that was to emit a custom event with the scene on $root, which is listened by the component where the controller lives. It acts likes a bus.

I am pretty sure there are better solutions, but at least it is working and flexible enough for my case. Any suggestion is welcome!