Jump to content
Search Community

Search the Community

Showing results for 'airpods' in content posted in GSAP.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • GreenSock Forums
    • GSAP
    • Banner Animation
    • Jobs & Freelance
  • Flash / ActionScript Archive
    • GSAP (Flash)
    • Loading (Flash)
    • TransformManager (Flash)

Product Groups

  • Club GreenSock
  • TransformManager
  • Supercharge

Categories

There are no results to display.


Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Personal Website


Twitter


CodePen


Company Website


Location


Interests

Found 94 results

  1. DrH

    Gsap is not defined

    Hello, Im new in this animation cooding so when i add the script src for scroll trigger in my html and when i copy some of the codes that are on the forums Like Apple Airpods pro animation ot dont work. This is what always pop out when i try it
  2. https://gsap.com/docs/v3/Plugins/ScrollTrigger/ It's because one of those is a tween on a ScrollTrigger with scrub: 1 - so it will take 1 second to catch up to the scroll position - and the other one is natively scrolling. So there will always be a discrepancy between the two - which will only become more apparent the faster you scroll. If you want both to behave the 'exact same', set scrub: true instead of scrub: 1 to your airpods ScrollTrigger. You'll lose the smoothness of the scrub then, of course. Or instead tween the 'over-scrolling' of the video via a ScrollTrigger that also has a numeric scrub of 1 set. But then, one way or another, you'll get a discrepancy again between that video container and the subsequent containers which would scroll natively. At this point you might end up in a 'tween everything' approach like Mitchel (@mvaneijgen) suggested in his earlier answer with the thread he linked to. An alternative to that approach could be to use overall smooth-scrolling instead, e.g. via ScrollSmoother alongside scrub: true on the airpods ScrollTrigger. Technically it's also a 'tween everything' approach - just on another level. And you'll lose some native browser features like e.g. jump-to search via F3. Is it worth the extra mile? Depends on how much you're a sucker for detail and how much the - most of the time visually small - asynchrony bothers you. Is any one better than the other? Depends on you again. Each of them has its downsides, if you ask me. Personally I'd go with the overall smooth-srolling - but that is merely a suggestion, not a recommendation by any means. It will definitely add another level of complexity with some regards. The latter - here it was just to keep track of what marker is related to which ScrollTrigger. But it can also be a helpful tool if at any point in time you might need to target any specific ScrollTrigger on your page for whatever reason logic-releated.
  3. Then logically you'll need to make sure that your video is appearing on the page further up than it is now. You could e.g. calculate the distance it takes to scroll from when the 4s start fading out in your one ScrollTriggger until the point where your video enters the viewport now and then you'd know by how much you'd have to offset your video to the top for it to enter the viewport when the 4s start fading out. And this you'd have to of course do before you set up your ScrollTriggers for the video. Or - since your airpods Scrolltrigger is dependent on the window height anyway - just set a vh value that fits for you via CSS, e.g. via a negative margin-top on your video container. That is what I did in the codepen below. A bit of a warning though; keep in mind that since you have a numerical scrub on your airpods scrollTrigger, the scroll of the video and the fading out of the 4s will never be truly 'synced' - which will become more apparent when you scroll fast. You are adding the tweens for the fading of the video to your first timeline - which has a scrub set. I'm not sure if that is what you want to begin with, since you added the tweens at the very bottom of your JS after you created all the ScrollTriggers. And if you add it to the pinning Scrolltrigger like you do, of course it will only start fading in the opacity once the video has reached the top, and then the 'over-scrolling' you were trying to achieve wouldn't make any sense at all anymore. So you'll probably want to add the tweens to that other, non-pinning, ScrollTrigger instead and also set it to scrub. That out of the way, here's something from the article on the most common ScrollTrigger mistakes: https://gsap.com/resources/st-mistakes/#how-to-make-scrub-animations-take-longer ------ BTW - @GreenSock @Rodrigo @Cassie - there's a wrong link in that blue information box in that section of the article. It is an old URL which previously pointed to this content: https://gsap.com/docs/v3/Plugins/ScrollTrigger/#how-does-duration-work-with-scrub-true But although the general concept of how durations work with scrubbed: true is explained there, there isn't any mention of empty tweens as suggested in that blue information box - sort of confusing altogether. Edit: I also found a typo in the docs for the position parameter with regard to percentages, that I'm mentioning further down the post. Reporting it here, where it might be better to catch. ----- That second link explains how durations work with scrub: true, @newguy123 - you should have a thorough read on it to understand the concept. I added some comments in the codepen below that might help better understand it in combination with what the docs say. In that codepen I also make use of the aforementioned empty tween to create a 'gap' where nothing happens between the fading in and fading out. So I also got rid of your approach with the position parameter - of course you can do it with the position parameter, too, but you'd have to use the proper value - and for understanding how durations work with scrub: true to begin with it might be easier to work with empty tweens at first. Also, I'm pretty sure the value you use for the position parameter (i.e. "99%") again is invalid. Here's what the docs say with regard to percentage values in the position parameter. You see, a percentage value without any prefix is not listed in there. In your example you could in fact change it to "0%" and it would still behave exactly the same as it does now. https://gsap.com/resources/position-parameter/ That all said, here's the codepen. https://codepen.io/akapowl/pen/ExJNxJO
  4. Awesome thanks @akapowl For the video, as per your suggestion, I added the 2nd scrolltrigger for the video to make it play automatically at a different time, than what its container reaches the top of the viewport. This works great. I like the way AAA and BBB scrolls past, over the video in usual fasion, so that part is great also. The next bit of my troubles, are that I want the entire video (ie both scrolltriggers for the bunny video), to come in slightly earlier in the scroll. Currently the Airpods scroll completes, and after it is done, it scrolls out of view and the video scroll in. It would be great, if I can have the video coming in already, at the part where the Airpod's title "4444444" starts fading out. I can't figure out how to do this and seems the video will always only come in AFTER the Airpods scroll fully completes. Also, I adjusted the video scroll some more, to also fade in and fade out. The problem with this part is that my initial fade in, seems to take too long. No matter what I set the duration to, it doesnt seem to make a difference. For the fading out part, same thing, it takes too long to fade out. Also, it start to fade out too soon. I only want it to start fading out when "BBB" is almost out of view, but before "The End" comes in. https://codepen.io/newguy123/pen/dyLpxqp
  5. Hi Guys I have 1 X Scrolltrigger, ie the Apple Airpods example, with 4 titles appearing over it as you scroll. This works great, as expected. However, immediatly AFTER the 1st scrolltrigger finishes, I want the next one to start as it come in to view. Its a video and it should loop and only start playing when it comes into view. What's more, I want the video to STAY PINNED for a bit, enough for the next 2 titles "AAA" and "BBB" to scroll past. Then the video should unpin scroll out of view while the next section "THE END" scrolls into view. I have 2 troubles here. I can't seem to pin the video and I cant seem to play it when it comes into view, while the 2 titles scrolls over while the video is pinned. https://codepen.io/newguy123/pen/NWmReyM
  6. 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); }
  7. Hi Guys This is more of a general hosting question, and not so much necessarily a GSAP specific question. We built a site based on the GSAP Airpods Pro scroll sample. Our site however loads around 900 frames, and not 147 like the Airpods example. Now the problem. We tested on 2 different hosting providers. The one provider, loads the files just fine, but the other comes up with a bunch of 508 and 404 errors, even though the files are there. In contacting the hosting provider support, they say there is nothing they can do as their servers are setup with brute force attack protection. Essentially when loading the site, its pulling so many resources that the server thinks its being attacked, and then blocks the requests, resulting in only half the site loading. This is specific to a single hosting provider, and as I say, a different hosting provider does not have this probem at all. Unfortunately the provider that works fine, is not in UK, and we would need one based in the UK. Any recommendations or general advice?
  8. 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); }
  9. Hi As per the Apple Airpods example on GSAP, which currently only shows 1 image sequence in the example, what if I want to have 3 or 4 sections, each with its own sequence? Do I simply duplicate the existing code for the single section, and just rename the classes/ids in html for each section, and same in the javascript? Ie, I will then have 4 different scrolltriggers, each firing when its relevant section reaches it's start?
  10. Hello guys from GSAP community! You have created a cool tool, congratulations to you. And now, I'm trying to recreate the text animation in the second section from Apple's website: https://www.apple.com/airpods-pro/ The problem is that ScrollTrigger doesn't behave quite as I expected and instead of the Fade-In-Out effect on individual sentences like on the reference, I have the transparency of the entire text changing as soon as it enters the viewport. Can you please tell me what I'm doing wrong? Maybe someone has already tried to recreate this animation?
  11. Thank you @mvaneijgen! I completely agree. However, I still think that it's vital to understand how animated content affects SEO. And, more specifically, how GSAP's animations are perceived - does Google bot generally ignore all GSAP's animations and see the content only as it is displayed initially in html and css? There are always exceptions and certain content/pages can be more heavily animated to control all aspects of users' journey and perception - think product presentations or specific About pages. For example: https://www.apple.com/airpods-3rd-generation/ or https://i2-camera.polaroid.com/ How to make the call which elements are safe to animate (and how), if one has no idea how each choice will affect the SEO strategy? This becomes even more important when dealing with clients who rely on search traffic to get users on their pages and then use design (including animations) to convert them. For now, I'll be playing around with GSAP for my personal projects only and testing as much as possible but any large scale experimentation is outside my budget. And without having any idea how GSAP's animations are perceived by Google, I'm unable to recommend it to anyone (well, besides saying that "stuff will look pretty but there's a chance that no one will see it"). Essentially, I'm hoping that someone else ran into these same questions as I have and would be generous enough to share their experience and best practices discovered. Will keep this thread "unsolved" if that's ok - perhaps someone else will have something to share or my experiments will yield at least some concrete results that I could share. For now, all I could find was a video from 2017, where John Mueller "suggested" that partly visible content or content starting invisible and becoming visible when the rendering is finished, is treated as visible: So, with this in mind, it could be said the it's best practice to have content start at 0.5/0.7 opacity and animate to 1? Or have content sliding in from position only partly offscreen? Or have elements fully visible further down on page load and then use GSAP to do whatever you want with them as user scrolls down (for example: https://codepen.io/vitaeludus/pen/gOqQGXP)?
  12. Thanks for help! Here's an example that I almost managed to create, thanks to you! https://codepen.io/bysobi/pen/YzBEBpM I've come close, but I can't figure out the sequence of the animation. It seems too complicated. The website and the section I want to replicate: https://www.apple.com/ua/airpods-pro/ Question #1 I've almost managed to replicate the text animation. However, I encountered issues with the image. The initial appearance of text and image aligns with the example of apple. Problems arise during the display of the second block. It should be like this: 1. Scroll through text #1. It's almost gone, but image #1 is still visible and not hidden. 2. As soon as text #2 appears, image #2 smoothly appears. Question #2 Each block with text and image occupies a height of 100vh. I would like to keep it that way but reduce the amount of scrolling needed to initiate the animation. Thank you so much. I've spent over 18 hours but still couldn't solve this issue.
  13. Hello everyone! I got inspired by Apple's website: https://www.apple.com/airpods-pro/ I would like to ask for help from those who know how to replicate a block animation. Specifically, I'm interested in the ability to change text and images that are in a fixed position, meaning they do not change their position when scrolling. Could you help me with how to correctly use ScrollTrigger? This block
  14. the problem is that those examples are simple little squares ande circles and getting directly animated, where the airpods thing has its own function doing things. Its that function I'm having a hard time with to convert to React. Its getting the context of the canvas in the function, when the canvas is returned in the app, but the function is not seeing it for some reason
  15. I think you had not clicked save on the file before sharing. The original file you started with had the correct setup and I think you just removed everything and copied over the AirPods demo. In React you need to do proper cleanup in the useLayoutEffect function. I don't use React myself, but everything is explained in the example I've shared. My suggestion would be start with one of our React templates and copy over the logic you want one by one until something breaks.
  16. Hi @loganvenderlic and welcome to the GreenSock forums! If possible create a minimal demo that clearly illustrates the issue you're having. Besides the fact that you're not resetting the frame between both animations I can't see any issue in your code. The one advice I could give you is to create just one animation and then create the two ScrollTrigger instances where both use the same animation, since you're using the same target: const airPodsTween = gsap.to(airpods, { frame: frameCount - 1, snap: "frame", ease: "none", onUpdate: render, // use animation onUpdate instead of scrollTrigger's onUpdate }); const stOne = ScrollTrigger.create({ trigger: "#init-gsap", start: "top top", end: "bottom top", scrub: true, animation: airPodsTween, }); const stTwo = ScrollTrigger.create({ trigger: "#init-2", start: "top top", end: "bottom top", scrub: true, animation: airPodsTween, }); Happy Tweening!
  17. Hey guys, I've been working on setting up my own image sequence animations using ScrollTrigger and a method based on what @OSUblake already included in this thread. One issue I keep running into, though...I have one animation that I want to run twice during scroll, using two different triggers. It works fine on desktop, but on mobile, the first time it is supposed to run, it often runs too soon or is on a weird frame other than the first frame before I reach my trigger. Oftentimes, if I scroll past it, scroll back up, and then scroll back down, it works fine again. Here's a link to the project I'm working on: https://plantd.webflow.io/dev/product-copy-7-gsap-forum The element I'm animating is the #init-canvas <canvas> and its first trigger is #init-gsap. Can anyone offer any insight? By the way, I'm not sure if I have it set up correctly in my javascript to run the same animation twice and be triggered by two different triggers. Here's the gsap js I'm using (I can send more if you need it, or you can find all of my gsap js in the .gsap-scripts element near the bottom of the page): gsap.to(airpods, { frame: frameCount - 1, snap: "frame", ease: "none", scrollTrigger: {trigger: "#init-gsap",start: "top top",end: "bottom top", scrub: true }, onUpdate: render // use animation onUpdate instead of scrollTrigger's onUpdate});gsap.to(airpods, { frame: frameCount - 1, snap: "frame", ease: "none", scrollTrigger: {trigger: "#init-2",start: "top top",end: "bottom top", scrub: true }, onUpdate: render // use animation onUpdate instead of scrollTrigger's onUpdate}); Let me know if there's a better way I should be doing that! Thanks in advance for any help anyone can provide!
  18. Helloo, I have a image secuence working on scroll with scroll trigger, and it works mostly fine, but when i scroll the whole secuence and i scroll back, the console gives me this error: Uncaught TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(CSSImageValue or HTMLCanvasElement or HTMLImageElement or HTMLVideoElement or ImageBitmap or OffscreenCanvas or SVGImageElement or VideoFrame)'. Here is the js: gsap.registerPlugin(ScrollTrigger,ScrollSmoother); // Smooth Scroll var smoother = ScrollSmoother.create({ smooth:2,speed:2,effects:!0, }); function checkMedia(media) { if (media.matches) { smoother.kill() } else { smoother } } var m = window.matchMedia('(max-width: 820px)'); checkMedia(m); m.addListener(checkMedia); // Scroll Trigger Image Secuence const canvas = document.getElementById("hero-lightpass"); const context = canvas.getContext("2d"); canvas.width = 800; canvas.height = 500; const frameCount = 1100; const currentFrame = (index) => `/dist/images/animacionlonglow/naw_test${(index + 1).toString().padStart(4, "0")}.png`; const images = []; const airpods = { frame: 0 }; const imageUrls = []; for (let i = 0; i < frameCount; i++) { imageUrls.push(currentFrame(i)); } for (let i = 0; i < imageUrls.length; i++) { const img = new Image(); img.src = imageUrls[i]; images.push(img); } gsap.from(".scroll-title", { opacity: 0, y:100, duration: 1, delay: 3, }); gsap.to(airpods, { frame: frameCount + 1, snap: "frame", ease: "none", scrollTrigger: { trigger: ".canvas-container", start: "top top", end: "+=12000", pin: true, scrub: 0.5, onUpdate: render, images[0].onload = render; function render() { context.clearRect(0, 0, canvas.width, canvas.height); context.drawImage(images[airpods.frame], 0, 0); // . Texts Appear on Scroll / Frames if (airpods.frame >= 100 && airpods.frame < 310) { document.querySelector('#section-text-1').classList.add('active'); } else { document.querySelector('#section-text-1').classList.remove('active'); } if (airpods.frame >= 450 && airpods.frame < 600) { document.querySelector('#section-text-2').classList.add('active'); } else { document.querySelector('#section-text-2').classList.remove('active'); } if (airpods.frame >= 700 && airpods.frame < 900) { document.querySelector('#section-text-3').classList.add('active'); } else { document.querySelector('#section-text-3').classList.remove('active'); } if (airpods.frame >= 990 && airpods.frame < 1200) { document.querySelector('#section-text-4').classList.add('active'); } else { document.querySelector('#section-text-4').classList.remove('active'); }; }; Let see if someone know the issue, and also can give me a good way to preload all the image secuence before loading the page. Thanks a lot
  19. Hi @Klaas and welcome to the GreenSock forums! I'm not sure how feasible that is. GSAP ticker is ran 60 times per second so that means that the update callback of a GSAP instance is called on every tick. That would create a bit of a conundrum IMHO since you'll have to pause the timeline on every update, wait for the async code to be completed, then resume the timeline and in the next update (roughly 16 milliseconds later) pause it again. You could set the amount of times the ticker runs but that could create a new set of issues. Since the code you're using generates renders of the model, can you create all the models in on sit and use this approach by @OSUblake? https://greensock.com/forums/topic/25188-airpods-image-sequence-animation-using-scrolltrigger/?do=findComment&comment=121610 Sorry I can't be of more assistance. Hopefully this helps. Happy Tweening!
  20. Hi, I have landing page with many advanced tweens for example frame animation like AirPods Pro, 3 horizontal tweens with pictures and much much more. When page is loading for the first time it looks normal and the content page loads properly. But when I refresh page when isn’t on top, tweens don’t load well and page content overlaps to each other. Is this a known problem? For business reasons I can't share the code here and it’s too long
  21. Hi @maculotti.a@gmail.com, welcome to the GreenSock forums and thanks for supporting GreenSock by being a Club member! I think the issue here is the fact that you have to take into account the size and separation of each frame in the spritesheet and then accommodate the size in the container in order to scale the position and separation accordingly. The spritesheet is a 3600px square with 6 rows and 6 columns, so why are you using these dimensions? var spriteSheet = { width: 778, height: 778, }; When you change those to 600 it works, but the issue is that the spritesheet doesn't seems to be put together properly, since it looks quite weird as you can see: https://codepen.io/GreenSock/pen/BaPKvYo One alternative is to break the spritesheet into single images and use the approach from this airpods ScrollTrigger animation by @OSUblake Another alternative is to use the spritesheet with PIXIJS in order to get an even better performance than in regular canvas: https://codepen.io/osublake/pen/bqEamV Also you should really focus on getting the spritesheet positioned correctly first and then worry about moving it around. Sometimes the best approach is to forget about ScrollTrigger and focus on the correct HTML/CSS setup first, then get your GSAP Animations working as you expect and once you got all that, add ScrollTrigger to the mix. Hopefully this helps. Let us know if you have more questions. Happy Tweening!
  22. Elements with fixed position are taken out of document flow as well as elements with absolute position (unless the absolute element resides inside an element with relative position). Pin spacing is something that involves a few things, that's why there is a specific section for that in the ScrollTrigger Docs (scroll past the config options below the middle of the page where you'll find How does pinning work under the hood?) https://greensock.com/docs/v3/Plugins/ScrollTrigger That will depend on your setup and the level of experience you have with React. For starting is better to stick with useLayoutEffect and use useEffect in some specific cases (for example if you need to create a GSAP context instance and add animations to it based on state updates, but I don't want to create confusion here, just remember always start simple and then add complexity to your apps as you are scaffolding them). Also when working with Next is always a good idea to use this little bit by @OSUblake: https://greensock.com/react-advanced#useIsomorphicLayoutEffect I'd try to avoid creating too complex scenarios in React (and any other component based UI library for that matter) in this regard. Sure you could create a master timeline that contains every animation that you want to play in a specific sequence, but normally the logic sequence is to play them as they appear in the screen (for scroll-based animations and every other scenario to be honest, no much sense in playing an animation for an element that is not in the viewport of course). If you have a ver complex setup with a deep component tree, then it would be a good idea to implement something that tells component deeply nested that the previous component is ready so it's that component's turn to create it's animations. But again, this is a very deep topic that can create a lot of confusion if not handled properly. I remember working on a complex ScrollTrigger based site with Next and a lot of nested components and at the end what I did was to create some prop that was passed from the main component to it's children (where each animation was being created) in order to render everything properly. You could use React context for that as well. Keep in mind that in React the render order starts from the most deeply nested child until it reaches the main component in the tree, but again this is something that you have to look into as you work in your projects and not in every single setup since they will vary depending on the project's requirements. Finally in this case this seems to be happening only on development mode so just reverting the GSAP Match Media instance in the component's cleanup function seems to work better: useLayoutEffect(() => { const mm = gsap.matchMedia(); mm.add( "(min-width: 768px)", () => { const canvas = canvasRef.current; const ctx = canvas.getContext("2d"); canvas.width = window.innerWidth; canvas.height = window.innerHeight; const frameCount = 148; const currentFrame = (index) => `https://www.apple.com/105/media/us/airpods-pro/2019/1299e2f5_9206_4470_b28e_08307a42f19b/anim/sequence/large/01-hero-lightpass/${index .toString() .padStart(4, "0")}.jpg`; let images = [], hero = { frame: 1 }; const render = () => { // let image = images[hero.frame]; ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(images[hero.frame], 0, 0); console.log(hero.frame); //requestAnimationFrame(render); }; for (let i = 0; i < frameCount; i++) { let img = new window.Image(); img.src = currentFrame(i); images.push(img); } images[0].onload = render(); gsap .timeline({ onUpdate: render, scrollTrigger: { trigger: ref.current, end: () => "+=150%", pin: true, scrub: 0.5, markers: true } }) .to( hero, { frame: frameCount - 1, snap: "frame", ease: "none", duration: 1 }, 0 ); }, ref ); return () => mm.revert(); // <- Cleanup! }, []); Hopefully this clears things up a bit. Let us know if you have more questions. Happy Tweening!
  23. Hello again, I've spent some time this week working with Scroll trigger and now image sequences. But run into some issues that I'm hoping somebody can help out with. The issue I have is getting scrollTrigger to work correctly with canvas when pinning the element. On it's own I can get the scroll trigger to scrub the image sequence, and pin the section. However when I add it to another page with other elements I experience issues with the other elements. My assumption is that the elements are being triggered in the incorrect order so in some cases the first pin overlaps the second pin. When scrolled up and down the Canvas flips between transitions and positioned once it hits the end of its animation. My goal: Add multiple pinned sections on the page (from what I've read I might be able to use observer for this instead of scrollTrigger) Don't overlap the pinned sections. Refresh or reposition the other sections. Add back in the MatchMedia queries, so this only works on desktop devices (I'm able to do this part) Unsure about If I need to useLayoutEffect instead of useEffect move the bulk of the code out of the useEffect and pass in the relevant ones as deps The specific file I'm having issues with is the HeroScroll.jsx linked below. I've tried to take use the example from Airpods demos in the forums and update this to work in React. https://codesandbox.io/s/scroll-trigger-react-mulitiple-pins-b0jchy?file=/src/components/HeroScroll.jsx I feel I'm missing something major here but struggling to find the correct way to implement this. It maybe that I can use the observer here instead of a timeline, and assuming that can be used with matchMedia then I can give that a go. Thank you Sean
  24. Hi! I'm building a website for a client using ScrollTrigger and similar approach as the Airpods example from Codepen. In the Airpod example the animation ( frames ) are played using the scroll, my question is how can one add start to sections of the animations using just one scroll. Using the airdpod example what I would like to achieve is: - 1 scroll => animation plays from frame 0 to frame 40 then stops, - another scroll animation plays from 41 to 100, - another scroll from 100 to 148. So I would have 3 animation sections which would start to play with one scroll each. Haven't added my example to codepen since it's very similar to the Airdpod example, if I could get some ideas or which GSAP plugin to use in combination with scroll trigger, woudl be much appreciated. Thank you!
  25. Hi, I've adjusted the scrub to true and the issue persists. I've added a second title in green to more easily show the issue. As you can see the red title animation immediately starts playing, with the red title animating once the previous animation is done (and this is correct behavior). However, the AirPods animation seems to be stretched over this whole timeline. Edit: Codepen has been adjusted: https://codepen.io/jvlvl-z/pen/gOKxaKe
×
×
  • Create New...