Jump to content
Search Community

Gsap Scroll trigger not behaviing on Mac

sarthak950 test
Moderator Tag

Recommended Posts

Without a minimal demo, it's very difficult to troubleshoot; the issue could be caused by CSS, markup, a third party library, a 3rd party script, etc. Would you please provide a very simple CodePen or Stackblitz that illustrates the issue? 

 

Please don't include your whole project. Just some colored <div> elements and the GSAP code is best. See if you can recreate the issue with as few dependancies as possible. Start minimal and then incrementally add code bit by bit until it breaks. Usually people solve their own issues during this process! If not, at least we have a reduced test case which greatly increases your chances of getting a relevant answer.

 

See the Pen aYYOdN by GreenSock (@GreenSock) on CodePen

that loads all the plugins. Just click "fork" at the bottom right and make your minimal demo

 

Using a framework/library like React, Vue, Next, etc.? 

CodePen isn't always ideal for these tools, so here are some Stackblitz starter templates that you can fork and import the gsap-trial NPM package for using any of the bonus plugins: 

 

Please share the StackBlitz link directly to the file in question (where you've put the GSAP code) so we don't need to hunt through all the files. 

 

Once we see an isolated demo, we'll do our best to jump in and help with your GSAP-specific questions. 

Link to comment
Share on other sites

here is the animation handeler Canva.js
 

import gsap from "gsap";

import ScrollTrigger from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);

let winCount = 20;
// detect if the user is on mobile
if (window.innerWidth < 768) {
    winCount = 8;
}

const slidetimeline = gsap.timeline({
    scrollTrigger: {
        trigger: "body",
        start: "top top",
        end: `+=${window.innerHeight * winCount}`,
        scrub: true,
        pin: true,
        anticipatePin: 1,
    },
});
slidetimeline
    .to("#slide1", {
        // maskPosition: "0% -4.5vh",
        clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)",
        duration: 2,
    })
    .to(".contextText1", {
        opacity: 1,
        duration: 1,
    }, "-=1.5")
    .to("#slide2", {
        // maskPosition: "0% -4.5vh",
        clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)",
        duration: 2,
    }, "+=1")
    .to(".contextText2", {
        opacity: 1,
        duration: 1,
    }, "-=1.5")
    .to("#slide3", {
        // maskPosition: "0% -4.5vh",
        clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)",
        duration: 2,
    }, "+=0")
    .to(".contextText3", {
        opacity: 1,
        duration: 1,
    }, "-=1.5")
    .to("#slide4", {
        // maskPosition: "0% -4.5vh",
        clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)",
        duration: 2,
    }, "+=0")
    .to(".contextText4", {
        opacity: 1,
        duration: 1,
    }, "-=1.5")
    .to("#slide5", {
        // maskPosition: "0% -4.5vh",
        clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)",
        duration: 3,
    }, "+=0");

const index = 10000;
const frameCount = 240;
const currentFrame = (index) => (
    `/Aquatica/Renders/Char_Turn_Around${(10000 + index).toString()}.webp`
);

// Example usage:
const images = [];

for (let i = 0; i < frameCount; i++) {
    const img = new Image();
    img.src = currentFrame(i);
    images.push(img);
}

Promise.all(images.map((img) => {
    return new Promise((resolve) => {
        img.onload = resolve;
    });
})).then(() => {
    // Initialize scroll animations here
    ScrollTrigger.refresh();
});

// Canvas setup
const canvas = document.getElementById("canvas");
const context = canvas.getContext("2d");
canvas.width = 1158;
canvas.height = 770;

// Airpods animation setup
const airpods = {
    frame: 0,
};

// Extend the duration to add time for fade-in and fade-out
const totalAnimationDuration = 10;
const frameTransitionDuration = totalAnimationDuration / frameCount;

let count = 0;
const modelTextList = document.getElementsByClassName("modelText");
// Step 1: Add the debounce function
function debounce(func, wait) {
    let timeout;
    return function () {
        const context = this,
            args = arguments;
        clearTimeout(timeout);
        timeout = setTimeout(function () {
            func.apply(context, args);
        }, wait);
    };
}

// Step 2: Create a debounced version of your render function
const debouncedRender = debounce(render, 0); // Adjust the wait time as needed

// Step 3: Use debouncedRender in your animations

// const model = gsap.timeline({
//     scrollTrigger: {
//         trigger: "canvas",
//         start: "top top",
//         end: `+=${window.innerHeight * winCount}`,
//         scrub: true,
//         pin: true,
//         anticipatePin: 1,
//     },
// });

for (let i = 0; i < frameCount - 1; i++) {
    slidetimeline.to({}, {
        duration: frameTransitionDuration,
        onUpdate: function () {
            console.log("Frame Count:", i);
            debouncedRender(); // Use the debounced render function
        },
    }, `+=${frameTransitionDuration}`)
        .to(airpods, {
            frame: i + 1,
            snap: "frame",
            duration: frameTransitionDuration,
            onUpdate: function () {
                console.log("Frame Count:", i);
                debouncedRender(); // Use the debounced render function
            },
        });

    if (
        i === 25 || i === 61 || i === 93 || i === 116 || i === 151 || i === 176 ||
        i === 215
    ) {
        slidetimeline.to(modelTextList[count], {
            opacity: 1,
            duration: 2,
        }, "-=1")
            .to(modelTextList[count], {
                opacity: 0,
                duration: 2,
            }, "+=0.5");
        count++;
    }
}
images[0].onload = render;

function render() {
    context.clearRect(0, 0, canvas.width, canvas.height);

    const img = images[airpods.frame];

    // Calculate the scaling factors to fit the image within the canvas
    const scaleX = canvas.width / img.width;
    const scaleY = canvas.height / img.height;
    const scale = Math.min(scaleX, scaleY);

    // Calculate the dimensions after scaling
    const scaledWidth = img.width * scaleX;
    const scaledHeight = img.height * scaleY;

    // Calculate the position to center the scaled image on the canvas
    const offsetX = (canvas.width - scaledWidth) / 2;
    const offsetY = (canvas.height - scaledHeight) / 2;

    // center the image
    const offX = (canvas.width - img.width) / 2;
    const offY = (canvas.height - img.height) / 2;
    // Draw the scaled and centered image
    context.drawImage(img, offsetX, offsetY, scaledWidth, scaledHeight);
    // context.drawImage(img, offX, offY, img.width, img.height);
}
Link to comment
Share on other sites

Hi,

 

Sorry but as stated without a minimal demo there is not much we can do. On top of that vague details like "broken", "not working", "not behaving" really don't help as well. As mentioned we need a minimal demo that illustrates the problem, a clear description of the problem and the steps to reproduce it as well.

 

Happy Tweening!

Link to comment
Share on other sites

@Rodrigo sir the exact description of the problem is that i have created a scroll trigger animation on the website mentioned above the website is seem less on the windows but when opened in a mac
the scroll trigger seems not to register the scroll the animation dont progress forward but the scroller moves forward
https://drive.google.com/file/d/1u4PCvisyKDYPyNHR1rZoGYZOufUSmVG2/view?usp=sharing
i tri
ed to replicate it on codepen but was not able to sorry for that it might be some of my mistake Just need some guidence and help

Link to comment
Share on other sites

Hi,

 

Sorry to hear about the problems.

 

Unfortunately there is not a lot we can do if you can replicate it in a minimal demo. For the details you porvide it seems that something else in your site/app is interfering with your code, the only suggestion I can give you is to start removing some parts of your projects until it starts working again, maybe start from a new project from scratch with just the HTML, styles and the animations and see if they work in Mac and then start adding other scripts and parts of your project until it breaks. Then you'll know what is causing the issue.

 

Finally this doesn't seem to be a GSAP related problem but something else in your code.

 

Happy Tweening!

Link to comment
Share on other sites

A developer refered my friend that using framework like react or next js will eleminate this issue but i dont get the point why that might do with this
do u have any experience with that
also have u seen the video that i have attached what my theory says is that the canvas that is rendering the images is causing the lag but i have seen apple doing it with 1000's of images with not prob

can u tell me where i am loosing the performance

const index = 10000;
const frameCount = 240;
const currentFrame = (index) => (
    `/Aquatica/Renders/Char_Turn_Around${(10000 + index).toString()}.webp`
);

// Example usage:
const images = [];

// Function to preload an image and store it in the images array
const preloadImage = (index) => {
    const img = new Image();
    img.src = currentFrame(index);
    img.onload = () => {
        console.log(`Image ${index} loaded`);
        // You can add additional logic here if needed
    };
    images.push(img);
};

// Preload all images
for (let i = 0; i < frameCount; i++) {
    preloadImage(i);
}


// Canvas setup
const canvas = document.getElementById("canvas");
const context = canvas.getContext("2d");
canvas.width = 1158;
canvas.height = 770;

// Airpods animation setup
const airpods = {
    frame: 0,
};

// Extend the duration to add time for fade-in and fade-out
const totalAnimationDuration = 10;
const frameTransitionDuration = totalAnimationDuration / frameCount;

let count = 0;
const modelTextList = document.getElementsByClassName("modelText");
// Step 1: Add the debounce function
function debounce(func, wait) {
    let timeout;
    return function () {
        const context = this,
            args = arguments;
        clearTimeout(timeout);
        timeout = setTimeout(function () {
            func.apply(context, args);
        }, wait);
    };
}

// Step 2: Create a debounced version of your render function
const debouncedRender = debounce(render, 0); // Adjust the wait time as needed


for (let i = 0; i < frameCount - 1; i++) {
    slidetimeline.to({}, {
        duration: frameTransitionDuration,
        onUpdate: function () {
            console.log("Frame Count:", i);
            debouncedRender(); // Use the debounced render function
        },
    }, `+=${frameTransitionDuration}`)
        .to(airpods, {
            frame: i + 1,
            snap: "frame",
            duration: frameTransitionDuration,
            onUpdate: function () {
                console.log("Frame Count:", i);
                debouncedRender(); // Use the debounced render function
            },
        });

    if (
        i === 25 || i === 61 || i === 93 || i === 116 || i === 151 || i === 176 ||
        i === 215
    ) {
        slidetimeline.to(modelTextList[count], {
            opacity: 1,
            duration: 2,
        }, "-=1")
            .to(modelTextList[count], {
                opacity: 0,
                duration: 2,
            }, "+=0.5");
        count++;
    }
}
images[0].onload = render;

function render() {
    context.clearRect(0, 0, canvas.width, canvas.height);

    const img = images[airpods.frame];

    // Calculate the scaling factors to fit the image within the canvas
    const scaleX = canvas.width / img.width;
    const scaleY = canvas.height / img.height;
    const scale = Math.min(scaleX, scaleY);

    // Calculate the dimensions after scaling
    const scaledWidth = img.width * scaleX;
    const scaledHeight = img.height * scaleY;

    // Calculate the position to center the scaled image on the canvas
    const offsetX = (canvas.width - scaledWidth) / 2;
    const offsetY = (canvas.height - scaledHeight) / 2;

    // center the image
    const offX = (canvas.width - img.width) / 2;
    const offY = (canvas.height - img.height) / 2;
    // Draw the scaled and centered image
    context.drawImage(img, offsetX, offsetY, scaledWidth, scaledHeight);
    // context.drawImage(img, offX, offY, img.width, img.height);
}

 

Link to comment
Share on other sites

Without a minimal demo, it's very difficult to troubleshoot; the issue could be caused by CSS, markup, a third party library, a 3rd party script, etc. Would you please provide a very simple CodePen or Stackblitz that illustrates the issue? 

 

Please don't include your whole project. Just some colored <div> elements and the GSAP code is best. See if you can recreate the issue with as few dependencies as possible. Start minimal and then incrementally add code bit by bit until it breaks. Usually people solve their own issues during this process! If not, at least we have a reduced test case which greatly increases your chances of getting a relevant answer.

 

See the Pen aYYOdN by GreenSock (@GreenSock) on CodePen

that loads all the plugins. Just click "fork" at the bottom right and make your minimal demo

 

Using a framework/library like React, Vue, Next, etc.? 

CodePen isn't always ideal for these tools, so here are some Stackblitz starter templates that you can fork and import the gsap-trial NPM package for using any of the bonus plugins: 

 

Please share the StackBlitz link directly to the file in question (where you've put the GSAP code) so we don't need to hunt through all the files. 

 

Once we see an isolated demo, we'll do our best to jump in and help with your GSAP-specific questions. 

Link to comment
Share on other sites

Please don't ping me or other users on threads, we get notifications about new posts in threads so there is no need for that.

 

Once again and as it's been stated several times, without a minimal demo there is not much we can do about this or any other issue.

 

Finally I already mentioned that this seems more related to some specific MacOS thing than a GSAP related issue. If this (whatever it is because you've been giving us just vague descriptions of this issue) happened in every browser and a codepen demo, there would be grounds to call this a GSAP related issue.

 

If you want you can contact us for paid consulting or post in the Jobs & Freelance forums to get the help you seem to require for this.

 

Happy Tweening!

Link to comment
Share on other sites

Your debounce logic looks flawed to me. I'd bet that's what makes it appear to lack performance. Every time debouncedRender() gets called in the onUpdate, it's resetting the wait time, so the only time it'll actually render is when there are NO onUpdate calls within a certain amount of time (the wait time). I don't understand why you're even implementing that debounce logic. I'd get rid of it if I were you. I also don't understand why you're running that onUpdate in a spacer tween that's not even animating anything. And then you're creating 2 tweens for every single frame? It just all seems rather inefficient to me. You only need to call that render function when the frame changes too, not on every update. 

 

Like Rodrigo said, this is probably well into the realm of custom consulting that we can't really provide in these free forums. You can contact us if you want to explore paid consulting options. 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...