DevC Posted February 9, 2022 Share Posted February 9, 2022 Tweenings Greetings, I've shared a demo that works okay in codepen, but has many syncing issues in prod (react). I'd like to know if there is a better way to do what I'm doing here. I'm also curious to find some docs on helping gsap get initialized before rendering. Seem to have the odd refresh where my text treatment is all messed up. After initial text and video wipe this should happen: With the frame cuts of the video the span in "The next number is" {1} should update. With the frame cuts the bg gradient should also update. On repeat is should stay in sync with the video. Thanks for any help. First time forum asker. See the Pen bGYWNvR by dcha (@dcha) on CodePen Link to comment Share on other sites More sharing options...
Solution OSUblake Posted February 10, 2022 Solution Share Posted February 10, 2022 Welcome to the forums @DevC One issue with your syncing is that you are not waiting for your video to load. For example, if I cache bust the URL to your video, video.duration will be NaN. If you need to sync up stuff, there are at least 3 different ways I can think of. 1. You add an event listener like timeupdate to your video, and apply changes based on the video's currentTime. 2. Instead of doing video.play(), you actually animate the video with GSAP. Something like this. .to(video, { currentTime: video.duration, duration: video.duration, ease: "none" }) 3. Instead of using video, you animate each frame using canvas and a bunch of images. See the Pen zYPwNEz by GreenSock (@GreenSock) on CodePen 3 Link to comment Share on other sites More sharing options...
DevC Posted February 13, 2022 Author Share Posted February 13, 2022 Thanks @OSUblake you lead me on the right path. For browsers of the future, I ended up using the video playback/currentTime as the progress ticker for the timeline. That did the trick. Something like this: function startVideo(timeline) { if (heroVideoRef && heroVideoRef.current && timeline) { const percent = heroVideoRef.current.currentTime / heroVideoRef.current.duration timeline.progress(percent) } } 2 Link to comment Share on other sites More sharing options...
Alan Kell Posted July 14, 2023 Share Posted July 14, 2023 Hi @OSUblake, I've ben trying to implement the second suggestion you made above as I am looking to progress a video as the gsap timeline progresses. I've not been able to get it to work yet though unfortunately. I've tried the following so far; let tl = gsap.timeline(); tl.to("#centerCompanyVideo1", { currentTime: 10, duration: 10, ease: "none" }, '+=0'); This is loading the video (which I have in the html as <video id="centerCompanyVideo1" class="centerCompanyVideo" preload="auto" src="~/images/ReportVideo.mp4"></video>) but it isn't updating the currentTime property at all - the video just shows a still preview. It does wait the 10 second though before completing. Can you see anything obviously wrong here - I'm struggling to make progress with it. Thanks in advance for any help, Alan Link to comment Share on other sites More sharing options...
GSAP Helper Posted July 14, 2023 Share Posted July 14, 2023 Hi @Alan Kell It's pretty tough to troubleshoot without a minimal demo - the issue could be caused by CSS, markup, a third party library, your browser, an external script that's totally unrelated to GSAP, etc. Would you please provide a very simple CodePen or Stackblitz that demonstrates the issue? Please don't include your whole project. Just some colored <div> elements and the GSAP code is best (avoid frameworks if possible). See if you can recreate the issue with as few dependancies as possible. If not, incrementally add code bit by bit until it breaks. Usually people solve their own issues during this process! If not, then at least we have a reduced test case which greatly increases your chances of getting a relevant answer. Here's a starter CodePen that loads all the plugins. Just click "fork" at the bottom right and make your minimal demo: See the Pen aYYOdN by GreenSock (@GreenSock) on CodePen If you're using something like React/Next/Vue/Nuxt or some other framework, you may find StackBlitz easier to use. We have a series of collections with different templates for you to get started on these different frameworks: React/Next/Vue/Nuxt. 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 More sharing options...
Alan Kell Posted July 17, 2023 Share Posted July 17, 2023 Thanks for coming back to me - that makes complete sense. I've created a CodePen example of what I'm struggling with here - See the Pen RwqMeoO by Alan-Kell-the-scripter (@Alan-Kell-the-scripter) on CodePen On this demo a video will load (whilst invisible), will fade in when loaded and then should start playing based on a timeline command. It loads, fades in but doesn't play based on the currentTime incrementing as I hoped it would. Any help or direction would be very much appreciated. Link to comment Share on other sites More sharing options...
Rodrigo Posted July 17, 2023 Share Posted July 17, 2023 Hi @Alan Kell, I think this is more related to the video file you're using more than anything else. Here is a fork of your codepen with a different video source working as expected: See the Pen eYQMwGx by GreenSock (@GreenSock) on CodePen As you can see this is not a GSAP related issue but something else with your video file. Check this post in order to know more about it and how to solve it: Hopefully this helps. Happy Tweening! Link to comment Share on other sites More sharing options...
Cyango Posted January 17 Share Posted January 17 Hi, I'm new to GSAP, I'm trying to implement the second option of this thread. But I wanted also the audio from the video to play, but somehow is not playing, maybe not possible when setting the currentTime. Other question i would like to know is: using GSAP as a video player using a special playhead, similar to the video editors out there. Is this possible with GSAP? if so is it possible to keep the running the video with its original FPS? I assume this is probably not possible, but worth questioning. The audio is not playing like this: useGSAP(() => { if (timelineInstance && mediaPlayerRef.current) { const animation = gsap.to(mediaPlayerRef.current, { currentTime: 10, duration: 10, ease: 'none', }); addAnimationToTimeline(animation); } }, [timelineInstance, mediaPlayerRef.current]); Link to comment Share on other sites More sharing options...
Rodrigo Posted January 17 Share Posted January 17 Hi @Cyango and welcome to the GSAP Forums! I believe the video is muted using the muted attribute in order to prevent autoplaying, but I'm not 100% sure about that. The main issue here is that the video is actually not playing, the video's current time is being updated by GSAP so regardless of the approach you use, the sound won't play. The only solution I can think of is to just play the video and create your animations in the timeline so it works out of the box: See the Pen wvOJmxm by GreenSock (@GreenSock) on CodePen But with this approach you'll run into this issue with Chrome if the user doesn't interact with the document you unmute the video: https://stackoverflow.com/questions/49930680/how-to-handle-uncaught-in-promise-domexception-play-failed-because-the-use Then if you remove the muted attribute and then unmute the video you'll have pretty much the same problem: https://stackoverflow.com/questions/51041580/muted-autoplay-video-shows-error-play-failed-because-the-user-didnt-interact Unfortunately I never played enough with video in order to handle all of this so I can't really think of a simple solution that works in every possible scenario. I tried all these and neither worked: window.focus(); document.documentElement.focus(); It seems that the focus method is not interpreted as a user interaction 🤷♂️ Hopefully this helps. Happy Tweening! Link to comment Share on other sites More sharing options...
Cyango Posted January 17 Share Posted January 17 Thanks for the quick reply. I already have those issues handled in the code before, and the video was not muted. To give you a bit more context, i'm using React and Zustand to set the timelineInstance so I can use it anywhere. This is where i initialise it (in a component): useGSAP( () => { const options: gsap.TimelineVars = { paused: true, onComplete: () => { setPlayingMode(PlayingModes.STOPPED); }, onUpdate: () => { const elapsedTime = timeline.current?.time() || 0; setElapsedTime(elapsedTime); }, }; timeline.current = gsap.timeline(options); setTimelineInstance(timeline.current); // zustand action }, { dependencies: [activeScene?.id], scope: gsapContainerRef }, ); and then in another component i was now trying to set the currentTime: useGSAP(() => { if (timelineInstance && mediaPlayerRef.current) { const animation = gsap.to(mediaPlayerRef.current, { currentTime: 10, duration: 10, ease: 'none', }); addAnimationToTimeline(animation); } }, [timelineInstance, mediaPlayerRef.current]); But i understand the video is not actually playing only setting the currentTime, so i now tried to do something like this: useGSAP(() => { if (timelineInstance && mediaPlayerRef.current) { const animation = gsap.to(mediaPlayerRef.current, { duration: 10, ease: 'none', onStart: () => { mediaPlayerRef.current?.play().catch((error) => console.log(error)); }, onComplete: () => { mediaPlayerRef.current ?.play() .then(() => { mediaPlayerRef.current?.pause(); }) .catch((error) => console.log(error)); }, }); timelineInstance.add(animation); } }, [timelineInstance, mediaPlayerRef.current, props.asset]); The issue I'm having now is that even calling timelineInstance.pause() somewhere else, the video doesn't pause. Am I doing this react flow with gsap correctly? My goal is to have a global timeline that commands the video playback and other html elements in sync always. Link to comment Share on other sites More sharing options...
GreenSock Posted January 17 Share Posted January 17 Perhaps this answer will help: It has a helper function I wrote to make this a lot easier (if I'm understanding your goal correctly) Link to comment Share on other sites More sharing options...
Rodrigo Posted January 17 Share Posted January 17 Hi, 3 hours ago, Cyango said: The issue I'm having now is that even calling timelineInstance.pause() somewhere else, the video doesn't pause. Since you're using a state management for your app, why not create something there to control the video playback as well as the timeline? You mentioned an event (I'll assume a click or pointer event), so why not control the timeline and the video in the same component by watching a specific state update in order to play/pause both at the same time? Without knowing a lot about the structure of your project that seems like the simplest, easiest and cleaner way to handle something like this, for me at least. Happy Tweening! Link to comment Share on other sites More sharing options...
Cyango Posted January 17 Share Posted January 17 The project is actually very dynamic in terms of how many videos, audios and three.js elements it has. The goal is to have a master timeline (like Adobe After effects for example) that controls the videos and audios playback (if they exist in the canvas) and control three.js meshes and so on, where i can play/pause, delay and add keyframes for example to the current elements instantiated. I need to have the ability, for example, to play a video and be able to create a new keyframe of a mesh rotating and in sync with the video playback at the custom defined time. Is GSAP able to achieve something like this? Because if so, I'm willing to go comercial license with it. Link to comment Share on other sites More sharing options...
GreenSock Posted January 17 Share Posted January 17 GSAP is just a JavaScript animation library, driven by requestAnimationFrame() and it's super flexible. As I linked to above, there are ways to have a GSAP timeline update the playhead of a video via JavaScript, yes. I just want to make it clear that it's not as if GSAP has some kind of built-in magical way of always synchronizing those perfectly, but JavaScript can be leveraged to accomplish at least some level of synchronization. Just don't expect it to alter the audio timeScale if you slowed down the GSAP timeline or something like that. Good luck! Link to comment Share on other sites More sharing options...
Cyango Posted January 17 Share Posted January 17 Yes that's why I'm liking gsap, because of it's flexibility. I don't need to have precision in the sync, but at least syncing in a seconds precision, could that be possible? So what I need to build is possible with gsap? About the example i gave earlier, do you think this is the correct approach in my case? I just needed an onPause callback somehow... Link to comment Share on other sites More sharing options...
Rodrigo Posted January 17 Share Posted January 17 13 minutes ago, Cyango said: About the example i gave earlier, do you think this is the correct approach in my case? I just needed an onPause callback somehow... As I mentioned in my previous post, use the same event you'll use to pause the timeline using state management, that's mostly a React/State-management thing than a GSAP related issue. Happy Tweening! Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now