Nuxt with LocomotiveScroll and Gsap
Asked Answered
B

2

1

I've been struggling to implement locomotive-scroll and Gsap into a Nuxt project. Something I believe to do with the DOM and SSR. I checked all the docs from scrollproxy Gsap, to Nuxt and locomotive, but I have no more clues.

If you guys have any recommendation, help is more than welcome. Thank you for your time.

Here are the errors

TypeError: Cannot read property 'scroll' of undefined
Uncaught TypeError: _triggers[_i].update is not a function
Uncaught TypeError: Cannot read property 'match' of undefined

Created in plugins/locomotive.js

import Vue from "vue";
import locomotiveScroll from "locomotive-scroll";

Object.defineProperty(Vue.prototype, "locomotiveScroll", {
  value: locomotiveScroll
});

Configured in nuxt.config.js

css: [
  //smooth scroll
  '@/assets/css/scroll.css',
],
plugins: [
  {
    src: "~/plugins/locomotive.js",
    mode: "client"
  }
],

Added in app.vue

<script>
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
import LocomotiveScroll from "locomotive-scroll"
</script>

Fired in the mounted hook of app.vue

this.locoScroll = new LocomotiveScroll({
  el: document.querySelector('.smooth-scroll'),
  smooth: true,
})

this.locoScroll.on('scroll', ScrollTrigger.update)

ScrollTrigger.scrollerProxy('.smooth-scroll', {
  scrollTop(value) {
    return arguments.length
      ? this.locoScroll.scrollTo(value, 0, 0)
      : this.locoScroll.scroll.instance.scroll.y
  },
  getBoundingClientRect() {
    return { top: 0, left: 0, width: window.innerWidth, height: window.innerHeight }
  },
  pinType: document.querySelector('.smooth-scroll').style.transform ? 'transform' : 'fixed',
})

ScrollTrigger.addEventListener('refresh', () => this.locoScroll.update())
ScrollTrigger.refresh()
Baa answered 1/3, 2021 at 13:47 Comment(4)
Please make a minimal, complete, and verifiable example using something like CodeSandbox if you'd like help debugging.Perak
Here is the CodeSandBox: Gsap works fine with Nuxt.js but as soon as i add LocomotiveScroll, it fail: codesandbox.io/s/nuxtjs-locomotivescroll-gsap-forked-nt34mBaa
Fix the errors that are preventing the code from running.Perak
I was able to fix the issue, the code works onload. Nuxt works well with Gsap. LocomotiveScroll does not work well with gsap, and will have to configure the scrollProxy. Also, locomotiveScroll interfere with the scroll and mess up with the cycle hooks of Nuxt. i dont know how to resolve it...Baa
K
0

try to focus on one issue at a time:

  • what do you struggle on with GSAP ? Did you tried this nuxt-gsap module ? Working super great on my side. ScrollTrigger is available there.
  • I'm not sure why do you use app.vue for locomotive-scroll but you should probably try the most basic use case in a simple page or component and plug it at max at the default layout IMO. Then, you could maybe look to optimize it.

If you achieve to install GSAP properly and are struggling with locomotive-scroll, you could maybe make a hosted example on Codesandbox. But if you don't want to bother too hard with it, you could maybe look for some Vuejs parallax packages, you may find something that suits you if GSAP is not enough.

Kironde answered 1/3, 2021 at 14:36 Comment(2)
Hi Kissu, and thank you for your quick reply. I use gsap in a page.vue instead of the app. I havent tried nuxt-gsap. Thanks again i will look for your recommendations. i uploaded my project to Github.Baa
Gsap does not react well to locomotiveScroll because it hijack the scroll. I want this smooth scroll effect so i use locomotive.Baa
G
0

this inside the scrolltrigger references itself so you need to put the locomotivescroll inside a variable to use without the this. In my case I went through parameters!

export default {
  data() {
    return {
      locoScroll: {},
    }
  },
  mounted() {
    this.locoScroll = new this.locomotiveScroll({ el: document.querySelector('#js-scroll'), smooth: true })
    window.addEventListener('resize', _.debounce(this.onlocoScrollResize, 100))

    this.locoScroll.scrollTo(0, 0, 0)

    this.$nextTick(() => {
      setTimeout(() => {
        const sections = document.querySelectorAll('section[data-scroll-11section]')
        this.resizeSectionsObserver(sections)
        this.locoScroll.update()
      }, 500)
    })

    let el = document.querySelector('#js-scroll')
    this.smooth(this.locoScroll, el)
  },

  methods: {
    smooth(scroll, el) {
      gsap.registerPlugin(ScrollTrigger)

      scroll.on('scroll', ScrollTrigger.update)

      ScrollTrigger.scrollerProxy(el, {
        scrollTop(value) {
          return arguments.length ? scroll.scrollTo(value, 0, 0) : +scroll.scroll.instance.scroll.y.toFixed(4)
        },
        getBoundingClientRect() {
          return {
            top: 0,
            left: 0,
            width: window.innerWidth,
            height: window.innerHeight,
          }
        },
        pinType: el.style.transform ? 'transform' : 'fixed',
      })
      ScrollTrigger.defaults({ scroller: el })
      ScrollTrigger.addEventListener('refresh', () => scroll.update())
      ScrollTrigger.refresh()
    },
    onlocoScrollResize() {
      this.locoScroll.update()
    },
    resizeSectionsObserver(elements) {
      const resizeCallback = () => {
        this.locoScroll.update()
      }
      const observer = new ResizeObserver(resizeCallback)
      elements.forEach(el => {
        observer.observe(el)
      })
    }
  },
  destroyed() {
    this.locoScroll.destroy()
    window.removeEventListener('resize', this.onlocoScrollResize)
  },
}

I'm using this code snippet in a Nuxt application I have a problem because it only works on the first call!

Grigsby answered 23/6, 2021 at 18:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.