Jump to content
GreenSock

Asored

BusinessGreen
  • Posts

    19
  • Joined

  • Last visited

About Asored

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

Asored's Achievements

  1. Hi there! First of all, sorry for always coming up with such tricky questions here. In my application, the user can create timelines via a UI. I store all created timelines in a variable and can access them later to play them as needed. Now I had the case that every item of a navigation should be animated on mouseenter. Here it became a challenge for me to find the right timeline for the right item. I added comments to my codepen code and I tried to create my project as simple as possible minimized. Simply asked, do I have the ability to get a reference in the timeline object to the elements it will animate? If so, I could just query that. Or is there a better solution for my use case?
  2. Oh, understood! Thank you! In my case I have no possibilities to add extra containers. My users can create some animation stuff with an UI. The DOM is always another and I don't know it. So this solution would not work for me. Is there any way with gsap.context() ?
  3. Hi there! I'm trying to create some very basic timelines which I can use on different places on the website / page, adding a class to an element. For example: Each element with the class .animate-me should animate y: -100 when entering the viewport. I have a problem with the scrollTrigger start and end values. When checking my attached CodePen, you will see that the animation for all .animation2 elements is triggering when the first element with the class .animation hits the center of the viewport. I think that is the expected behavior. But how could I make the trigger relative to the element which enters the viewport? In the CodePen, the second headline "Another headline" should start to animate when the second a.animation hits the center of the viewport. When iterating the triggers, I could choose the trigger selector to animate exactly this element. This works (.animation) But what if I want to animate other selectors in this timeline? (.animation2 in my example) Is there a best practice to handle such situations? I hope that I could describe my problem understandable. If not, please ask me
  4. Hi @Carl Thanks so much! Works like a charm!
  5. Hi everyone! I have a question which is very simple to ask, but where I currently do not know what to do. To make it clear, I've created a codepen on which I tried to reproduce my project as simple as possible. Basically, if I change a tween within a timeline, how do I make all the other tweens change with it? For example I could update the duration of a tween..and depending on the duration for a tween, the next tween in the timeline should change the startTime. Or do I understand something wrong? If my timeline has two tweens, both with the duration of 1 second. The structure will look like that: First Tween: Duration: 1, Start Time: 0 Second Tween: Duration: 1, Start Time: 1 When changing now the duration for the first tween to 5, for my understanding it should be: First Tween: Duration: 5, Start Time: 0 Second Tween: Duration: 1, Start Time: 5 But the start time remains to: 1. Please check my CodePen example. There you'll find some comments about this. The context is that I'm creating a timeline visualization. I need to change the values in real time. The UI is located in a different place than where the timeline creation is located. Therefore I have to work with a parent variable that stores the timelines globally. I think that should be fine. The user can change the duration of each tween inside an Input field. As result, the duration of the timeline changes successfully. But all other tweens ignores the change of this one tween. Do you have an idea how to achieve what I need? I hope that I was able to explain this understandably enough.
  6. Hi @GreenSock, understood. Thanks for the clarification! And yes, I think that would be the expected behavior – at least at the first thought. I think that would really make sense, also regarding the `start` and `end` arguments. Lets say the user defines a very small path. It is almost impossible to grab the end of the path to change it afterwards, because the animation is looping around the path. As workaround he can increase the duration to have the chance to grab the path dot. As solution we could just say: `end: 0.8` and as result, the end of the path will always be free for mouse interactions. Just to talk about a possible use case. Is there a workaround for me to force the arguments to have an effect – also for existing paths?
  7. Hi GreenSock! I've simplified the example removing the astronaut https://codepen.io/asored/pen/yLjpEwW But in general I talk about the following lines: MotionPathHelper.create(".astronaut", { path: "#path", pathWidth: 5, pathColor: "red", pathOpacity: 0.6, selected: true, start: 0.1, end: 0.5, duration: 5, ease: "power2.inOut" }); The documentation says: `You can optionally pass in a vars parameter to further configure the motion path helper. It's an object and can include any of the following properties:`. I've used the properties above and expect the following: - The width of the displayed path should be 5 - The path color should be not blue, but red - The path opacity should be 0.6 - The object should end on the half of the path - ..... and so on But all passed arguments seem to not have an affect. Just the basic blue path appears. Do I missunderstand something here? Are the arguments perhaps doing something different than I understand?
  8. @GreenSock @mvaneijgen Thanks so much for your feedback! I've got it to work calculating the viewBox dynamically depending on the path: // Calculate Viewbox let clientRect = document.querySelector(pathElementClass).getBBox(); let viewBox = clientRect.x+' '+clientRect.y+' '+clientRect.width+' '+clientRect.height; document.querySelector(pathElementClass).closest('svg').setAttribute('viewBox', viewBox); It works like a charm. GreenSock, great concept to recalculate also the motion values. But I think this will be too much. Its okay for me to have the new calculated viewBox on page reload. If I need this at some point, I will return to this post.
  9. Hi! As the documentation says, we can pass arguments to the `MotionPathHelper.create()` function. But all arguments are getting ignored for some reason. I've tried it also in your official example from the documentation page. Are there any breaking changes in the new MotionPathHelper version that require me to pass the arguments differently than what the documentation says?
  10. Hi GreenSock! Thanks for your feedback! Good hint with the `mouseenter`. I've completely overseen this. As you recommended, I've included some console.log() to my code to be sure that the code only runs once. Its important in this case that we have to separate the frontend output from the broken backend output where to code does not work as expected. Console – Frontend Output Creating timeline Set timeline settings Create Timeline animations Wait for event trigger Mouseenter event triggered Mouseleave event triggered Mouseenter event triggered Mouseleave event triggered Here everything seems to be okay, the way I would judge it. Console – Backend (where the DOM is loaded twice) JQMIGRATE: Migrate is installed, version 3.3.2 JQMIGRATE: Migrate is installed, version 3.3.2 Creating timeline Set timeline settings Create Timeline animations Wait for event trigger Creating timeline Set timeline settings Create Timeline animations Wait for event trigger Creating timeline Set timeline settings Create Timeline animations Wait for event trigger (3) Mouseenter event triggered (3) Mouseleave event triggered As you can see, in this case the DOM is rendered not twice, but three times! I hope they will fix the bug soon. But for now, I have to find a workaround for my application. 🤔 By the way: man thanks to you and your great community. This forum is just an enrichment! 👏 --EDIT-- I've found a temporary workaround by saving the timeline into a variable and checking if is active or not: flip.addEventListener("mouseleave", event => { if (tl.isActive()) { return; } tl.reverse(); }); May really not be the best solution, but I think in this case I can play with the weird DOM loading.
  11. I'm just playing with the incredible MotionPath plugin. The MotionPathHelper extension is very helpful for my users to build easily custom paths without struggling in Illustrator. But I already know. There will come questions like: "Why this is not responsive? We cannot use this in production if so". Is there a way to make such a scenario responsive and limit it to the viewport? https://codepen.io/asored/pen/jOxadKJ I don't think if we can play with nested SVG and if its a best practice to do so, but what if the user want to create a MotionPath from another element type like an image? In general I don't know what I get. The user can choose any HTML code and create paths for it. Have any of you thought about this specifically, how to solve something like this?
  12. Hey Cassie! Thanks very much! You're right. I've created a codepen with my code and simplified it removing the switch case blocks to focus on the relevant parts. In general this is what I try to do. A very simple flip box. As you can see, the code works. Also in my WordPress environment in frontend. But exactly the same code does not work correctly in backend when viewing trough the builder which loads it as iframe. The reverse finishes not on 100%, but pauses on 80-90%. Because of a current bug, the builder loads the DOM twice. I thought that this causes the error, because with a workaround for the builder which loads the DOM once, the animation works again, also in the builder. What do you think? https://codepen.io/asored/pen/bGMYaVw
  13. Thanks so much for your words! And also you, Rodrigo! Awesome people here in the forum! Regarding the problem I have, I badly cannot provide a codepen demo, because this plays inside a WordPress installation with a Page Builder. The Page Builder itself currently has a bug which loads the DOM content twice. (iframe). In the frontend view, where the DOM content is loading once, the reverse animation works well. But in the backend (builder) view, where the DOM is loaded twice, I get this strange behavior. As workaround I tried to force the javascript function where the animation was created only to load on the first DOM load..and yea, the reverse works then also in the builder view. This shows me: it really has anything to do with the double DOM loading. Very strange. I'll post the code from my javascript function. Maybe this helps. By the way. I see its a good practice to create the timeline outside of the for loop. In this case its not possible because I need to integrate date from the looped items. Or do you have a better idea? Here the code: async function gsapExample() { gsap.utils.toArray('.elem-flip-wrapper').forEach(flip => { let wrapper = flip; let box = wrapper.querySelector(".elem-flip-box"); let front = wrapper.querySelector('.elem-flip-front'); let back = wrapper.querySelector('.elem-flip-back'); let animationType = flip.getAttribute('data-type'); let duration = flip.getAttribute('data-duration'); let delay = flip.getAttribute('data-delay'); let trigger = flip.getAttribute('data-trigger'); let onComplete = flip.getAttribute('data-oncomplete'); let onStart = flip.getAttribute('data-onstart'); let onReverseComplete = flip.getAttribute('data-onreversecomplete'); animationType = animationType ? animationType : 'flip'; duration = duration ? duration : 1; delay = delay ? delay : 0; trigger = trigger ? trigger : 'hover'; onComplete = onComplete ? new Function (onComplete) : ''; onStart = onStart ? new Function (onStart) : ''; onReverseComplete = onReverseComplete ? new Function (onReverseComplete) : ''; const tl = gsap.timeline({ paused: true, onStart: function() { typeof onStart == 'function' ? onStart() : ''; }, onComplete: function() { typeof onComplete == 'function' ? onComplete() : ''; }, onReverseComplete: function() { typeof onReverseComplete == 'function' ? onReverseComplete() : ''; } }); gsap.set(wrapper, { transformStyle: "preserve-3d", transformPerspective: 1000 }); gsap.set(box, { transformStyle: "preserve-3d", transformOrigin: "50% 50%", }); gsap.set(back, { rotationY: 180, rotationZ: 180 }); switch (animationType) { case 'flip': tl.to(front, { rotationX: 180, duration: duration }, delay); tl.to(back, { rotationX: 180, duration: duration }, delay); break; case 'fade': gsap.set(back, { rotationX: 180 }); tl.to(front, { opacity: 0, duration: duration }, delay); tl.to(back, { opacity: 1, duration: duration }, delay); break; case 'fadeShrink': wrapper.style.overflow = 'hidden'; gsap.set(back, { rotationX: 180 }); tl.to(front, { scale: .8, opacity: 0, duration: duration/2 }, delay); tl.to(back, { opacity: 1, duration: duration }, delay); break; case 'fadeUp': wrapper.style.overflow = 'hidden'; gsap.set(back, { rotationX: 180, translateY: 500, opacity: 0 }); tl.to(front, { opacity: 1, rotationX: 180, duration: duration }, delay); tl.to(back, { translateY: 0, opacity: 1, duration: duration }, delay); break; case 'overlay': wrapper.style.overflow = 'hidden'; gsap.set(back, { rotationX: 180, translateY: 500, zIndex: 1 }); tl.to(back, { translateY: 0, duration: duration }, delay); break; case 'overlayShrink': wrapper.style.overflow = 'hidden'; gsap.set(back, { rotationX: 180, translateY: 500, zIndex: 1, scale: .9 }); tl.to(back, { translateY: 0, duration: duration }, delay); break; default: break; } switch (trigger) { case 'hover': flip.addEventListener("mouseover", event => { tl.play(); }); flip.addEventListener("mouseleave", event => { tl.reverse(); }); break; case 'click': flip.addEventListener("click", event => { if (flip.classList.contains('active')) { tl.reverse(); flip.classList.remove('active'); } else { flip.classList.add('active'); tl.play(); } }); default: break; } }) }
  14. I refer to the following post: In order to keep the forum clear, I created a new thread because the last question of the thread is about a different issue. That way others looking for it can find the solution faster. The issue is the following: In the environment I need to integrate a gsap animation currently is a small bug. The DomContentLoaded eventListener fires twice. I can't change this behavior and I need to play with it. This seems to be a problem for the tl.reverse(). The reverse animation stops until finishing. To make it more clear: I animate a translateX from 180 to 0..and the reverse() stops for example on 15. I think this is because there is triggered a second reverse() until the first is finished. Is there a way to say: "Hey! Please ignore other requests and animate only once"? Something like a force function to definitely finish the reverse animation. Or how could I handle a such scenario?
×