darkroomengineering / lenis

How smooth scroll should be
https://lenis.darkroom.engineering
MIT License
7.35k stars 315 forks source link

lenis.destroy() not removing events #282

Closed tobiasger closed 5 months ago

tobiasger commented 5 months ago

I might be thinking wrong about this, but I'm using the enter and leave hooks in Barba.js (page transitions) in order to create a new instance of Lenis when entering a new view and destroying the instance with its events when leaving the view.

var lenis;

function end(data) {
    // Destroy Lenis
    console.log("destroyed");
    lenis.destroy();
}

function begin(data) {
    console.log("begun");
    // Init Lenis
    var lenisWrapper = data ? data.next.container.querySelector("#scroll") : document.querySelector("#scroll");
    var lenisContent = data ? data.next.container.querySelector("#content") : document.querySelector("#content");
    lenis = new Lenis({
        wrapper: lenisWrapper,
        eventsTarget: document.querySelector("body"),
        content: lenisContent,
        lerp: 0.15,
    })
    lenis.on('scroll', function (e) {
        console.log(e.progress);
    });
    function raf(time) {
        lenis.raf(time)
        requestAnimationFrame(raf)
    }
    requestAnimationFrame(raf)
}

As mentioned, the begin() runs on barba.hooks.enter and end() runs on barba.hooks.leave. However, I can see when looking in the console that the progress gets written out two times when I go from one page to another and scroll, indicating that lenis.on('scroll') is still alive from the previous view. I can verify by logging "begun" when begin() runs and "destroyed" when destroy() runs that they get executed in the correct order, when looking in the console.

The readme says that lenis.destroy() "destroys the instance and removes all events", but that doesn't seem to be happening here. Am I misunderstanding something?

clementroche commented 5 months ago

can you provide a reproduction link ?

tobiasger commented 5 months ago

Unfortunately I'm doing this in a Wordpress environment, so not sure how I would recreate the routing for it. But I can try to provide that. In the meantime, am I understanding it right that the event should be removed when calling lenis.destroy()?

Some additional info is that I also have an IntersectionObserver that checks the direction that Lenis is scrolling whenever an intersection happens. On initial load, I get the correct 1 or -1 values. But when going from one view to another, the lenis.direction is constantly giving me 0. I assume this also has to do with two instances colliding.

tobiasger commented 5 months ago

Nevermind!

I added this to the mix:

var lenis;
var lenisAnimation;

...

function begin(data) {
    console.log("onEnter")
    destroyLenis();
    // Init Lenis
    var lenisWrapper = data ? data.next.container.querySelector("#scroll") : document.querySelector("#scroll");
    var lenisContainer = data ? data.next.container : document.querySelector("#container");
    var lenisContent = data ? data.next.container.querySelector("#content") : document.querySelector("#content");
    lenis = new Lenis({
        wrapper: lenisWrapper,
        eventsTarget: document.querySelector("body"),
        content: lenisContent,
        lerp: 0.15
    })
    lenis.on('scroll', function (e) {
        console.log(e.progress);
    });
    function raf(time) {
        lenis.raf(time)
        lenisAnimation = requestAnimationFrame(raf)
    }
    lenisAnimation = requestAnimationFrame(raf)
    initObserver();
}

function destroyLenis() {
    if (lenisAnimation) {
        cancelAnimationFrame(lenisAnimation);
        lenisAnimation = null;
    }
    if (lenis) {
        lenis.destroy();
        lenis = null;
        console.log("lenis destroyed", lenis);
    }
}

With the addition of creating a destroyLenis() function that would use lenis.destroy() and lenis = null, while simultaneously cancelling the animation frame, which I had missed to do. And that seems to have gotten rid of the problem! Sorry, I'm not experienced in destroying things properly...

I'll also refactor this and create a initLenis() function or similar.