Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...

Leaderboard

Popular Content

Showing content with the highest reputation since 09/27/2021 in all areas

  1. Looping back with a codepen. ✨ https://codepen.io/cassie-codes/pen/zYdxopE
    8 points
  2. There actually is a wonderful codepen demo out there, that shows how that second example could be done - the creator made use of GSAP 3.5.1 for it. https://codepen.io/jakewhiteleydev/pen/VwaXZZV Edit: And I just found this one recreating the works-section of that first video-example of yours. https://codepen.io/eleanxrg/pen/abZmdqe
    7 points
  3. Hi and welcome to the GreenSock forums, thanks for providing the demo. it seems your animation is set up to start with the menu open and then close it. I forced the animation to it's end (closed state) using progress(1) at the end of the timeline. it also seems your css is set up so that the page loads with the menu items visible. I set the opacity to 0 in the css and toggle it back to 1 once the page is loaded using gsap.set(".menu-overlay", {opacity:1}) https://codepen.io/snorkltv/pen/PojVQLv?editors=0110
    7 points
  4. Hi there Jenda, Welcome. ☺️ I'm not quite certain what you were trying to achieve with your first loop? Looks like you're looping through multiple containers but pinning the main one? I've removed that until you can tell me what your goal was! Here's a simplified loop pinning the numbers, is that what you were looking for? Positioning the first number would be down to styling things differently and pinning it for the duration - but again, I wasn't really sure what you were after. Hopefully this helps! https://codepen.io/GreenSock/pen/yLoYbpL
    6 points
  5. Hi and welcome to the GreenSock forums, Thanks so much for the clear demo. You can use an onComplete callback to apply clearProp:"all" to remove the inline styles. Be sure to inspect your box after the animation runs in the demo below https://codepen.io/snorkltv/pen/bGrVwxv?editors=1010 more on clearProps: https://greensock.com/docs/v3/GSAP/CorePlugins/CSSPlugin#h3-clearprops this video on callbacks and scope may help too
    6 points
  6. Hi Josh! Performance is very complicated topic as every situation is unique, so I don't have a silver bullet for you. Just from cursory glance at your code, here are some things that might help. First, maybe SVG isn't the best medium to use. SVG is slower than HTML, which is slower than canvas, which is slower than WebGL. If I have to animate hundreds of objects, I'm probably going to reach for canvas or WebGL first. PixiJS is good 2D WebGL renderer. You're also doing way too much work in your mouseover handler, and mousemove might be a better event to use. Notice in this demo how most of the work is done in the ticker function. The mouse handler just records where the mouse position is. https://codepen.io/GreenSock/pen/WNNNBpo Also in your mouse handler, you're creating 692 tweens, which is going to kill performance. You should only create a tween if you need to animate it. This might be easier if you made an object for every one of your polygons. I like to use class objects for this kind of stuff. Some pseudo code. const mapRange = gsap.utils.mapRange(0, 60, 1.2, 0.2); class Polygon { constructor(element) { this.element = element; this.getProp = gsap.getProperty(element); gsap.set(element, { transformOrigin: "50% 50%" }); } update(mouse) { const dist = ...; if (dist < 60) { gsap.to(this.element, { scale: mapRange(dist) }); } else if (this.getProp("scale") < 1) { gsap.to(this.element, { scale: 1 }); } } } const mouse = { x: 100, y: 100 }; const polys = gsap.utils.toArray("polygon").map(el => new Polygon(el)); gsap.ticker.add(() => { for (let i = 0; i < polys.length; i++) { polys[i].update(mouse); } }); Further optimization might involve only calculating if the element is within a set radius of the mouse. Using Math.sqrt() can be an expensive operation if you have to do a bunch of them. You can easily eliminate elements that are outside of the radius like this. // assumes x and y are the center of the element const dx = Math.abs(mouse.x - this.getProp("x")); const dy = Math.abs(mouse.y - this.getProp("y")); if (dx > 60 || dy > 60) { // not inside // check if we need scale to 1 animation needed if (this.getProp("scale") < 1) { gsap.to(this.element, { scale: 1 }); } } else { // calculate distance const dist = Math.sqrt(dx * dx + dy * dy); if (dist > 60 && this.getProp("scale") < 1) { gsap.to(this.element, { scale: 1 }); } else { gsap.to(this.element, { scale: mapRange(dist) }); } } You're also creating a mouse event for each polygon. It would be better to just have single event listener, and then figure out if the mouse is near a polygon. Yes, it requires a lot more work, but is much more optimized. Highly optimized animations will almost always require a lot more code.
    6 points
  7. Hi @Anael_, welcome to the forum ! πŸ’š There are many ways to solve this and I created one for you πŸ™‚. The problem when using position absolute is that you lose the .container dimension (width, height) and if the elements were not positioned with position absolute animation can get weird. So I created this, only animating the transform x, y, calculating the container dimensions and the left position of the element. https://codepen.io/nicofonseca/pen/XWareXV?editors=0110 I hope this helps πŸ™Œ
    6 points
  8. Hey Creek, If you want to handle logic within functions and pass parameters it may be best to use the methods that were made for that, like onComplete() or call() I'd also advise that you stay away from fancy arrow functions entirely until you have a better understanding of JS. Just stick with normal functions for now. (Some people may disagree with me here) But from experience teaching, there's less chance of getting confused about scope so it avoids unnecessary confusion. You can also create functions this way that are called from your timeline but instantiated elsewhere. This keeps your code nice and easy to read. I've put a playground together for you here. https://codepen.io/GreenSock/pen/VwzZWQm Also a note - I would consider myself experienced with JS and GSAP. I still have to put together minimal demos like the one above in order to test and understand things. When people ask questions here, the people that answer aren't necessarily drawing on knowledge that's immediately available. People helping have to: Read the post Read the code Extrapolate what the question is Read/reference the docs or search the forums for helpful threads Make a demo if one isn't provided Work out a solution Explain the solution It's quite time-consuming and a lot of the people in here do this voluntarily in addition to other work. You can help by keeping your posts as short as possible. Just outline the specific question and provide a minimal demo. Thanks
    6 points
  9. Hi @tibo78, when you use $('.whatever') jQuery will target all those elements from your page, so it is the same as document.querySelectorAll('.whatever'). So when you use those elements to animate with GSAP all are affected. You need to target only the elements you want to animate, you can do something like this: https://codepen.io/nicofonseca/pen/0aa7834959a64963e469a2d64e5328ec
    6 points
  10. Hello @BradLeeCoop - welcome to the forums. That probably is no out-of-the box effect that comes with any library, but something custom made with the help of WebGL - in this case I think they used pixiJS. There are some articles over on codrops explaining how to do similar effects with three.js - maybe these here can help you get started. https://tympanus.net/codrops/2019/10/23/making-gooey-image-hover-effects-with-three-js/ https://tympanus.net/codrops/2020/04/14/interactive-webgl-hover-effects/
    6 points
  11. Enhancement: I added the ability to define values in an Array for a more simplistic way to just go to certain values, split equally across the whole animation, like: keys: { scale: [1, 0.5, 1.5, 1] } To be clear, that first value in the Array isn't a "from" value - it's the first destination. So, for example, if scale is 0 when that tween renders for the first time, it'd go 0 > 1 > 0.5 > 1.5 > 1 over the course of the whole tween. So with this syntax, it gives you the flexibility to use the percent-based values when you need them spaced non-evenly or to use a non-linear ease, -OR- use the shorter Array-based syntax for evenly-spaced linear values. πŸ‘ I'm not set on the "keys" name, so if anyone has a better idea, I'm all ears. New plugin: gsap.registerPlugin({ name: "keys", init(target, vars, tween) { let tl = this.tl = gsap.timeline(), add = (prop, obj) => { let a = [], p; if (Array.isArray(obj)) { obj.forEach((value, i) => a.push({t: (i + 1) / obj.length * 100, v: value})); } else { for (p in obj) { p === "ease" || a.push({t: parseFloat(p), v: obj[p]}); } a.sort((a, b) => a.t - b.t); } a.forEach((kf, i) => { let v = {ease: obj.ease || "none", duration: kf.t - (i ? a[i - 1].t : 0)}; v[prop] = kf.v; tl.to(target, v); }); tl.duration() < 100 && tl.to({}, {duration: 100 - tl.duration()}); }, p this.tween = tween; this.ease = gsap.parseEase(vars.ease || "none"); for (p in vars) { p === "ease" || add(p, vars[p]); } }, render(ratio, {tl, tween, ease}) { tl.progress(ease(tween.progress())); } });
    6 points
  12. Hey @Syed Azam, welcome to the forum! πŸ’š You can do something like this: https://codepen.io/nicofonseca/pen/e81138427318c2826079e5c3f2ac4d41?editors=1010 The trick to achieve the mask effect is move the parent element to a direction and they child element to the opposite at the same time. gsap.to(parentElement, { xPercent: -100, duration:1 }); gsap.to(childElement, { xPercent: 100, duration:1, }); I hope this can help you. πŸ™‚
    6 points
  13. Hi Henrik - It's a little wonky, as I did it quickly. But you'll probably get the best result by creating a square with extra points halfway down the sides, then copying it and pulling those center points in to create the diamond sqdi.mp4 https://codepen.io/GreenSock/pen/jOLVeoa?editors=1010
    5 points
  14. @obaidnadeem This is definitely using some sort of WebGL for the rendering. GSAP works great for animating WebGL objects (Lots of example on the forms here). Interestingly enough, there's a Twitch Stream today covering using GSAP with WebGL shaders:
    5 points
  15. Just Added Width Expansion to my codepen above, feel free to adjust the Easing and Duration to match your Needs (Tranform X Y -50% doesn't seem to be working in this miniviewer, open codepen in another tab for correct display) https://codepen.io/blitzve0/pen/vYJGPaa
    5 points
  16. Hello @jenda In that case you could just set up an extra ScrollTrigger for the pinning of the "19" with an endTrigger set alongside of the end to easily tell where it is supposed to stop pinning, and let the ScrollTriggers within the loop handle the rest. The pen below shows how you you handle the ScrollTriggers in the loop it 'timingwise', dependent on the height of each .content You can certainly do that in the onLeave callback as to be seen in the pen below - but don't forget do fade them back in onEnterBack. Happy scrolling! https://codepen.io/akapowl/pen/c5c949193e94621afc717cbce169bc96
    5 points
  17. Hi there Mantrone! Welcome to the forums and thanks for joining club GSAP How about something like this as a starting point? https://codepen.io/GreenSock/pen/qBXdywG?editors=1010 You can control how the morph looks by tweaking the shapeIndex - read the docs for more info ☺️
    5 points
  18. The issue is the arrow function. The same goes for using let. IE is forever stuck using an older version of JavaScript. Most people use babel to do the conversion, or they don't even worry about IE because it's a waste of time as Microsoft doesn't even support it. var mobile_menu = gsap.timeline({ scrollTrigger: { trigger: "#site_content", toggleActions: "play none none none", start: "top top", end: "bottom bottom", onUpdate: function(self) { if(self.direction == -1){ mobile_menu.reverse(); } else if (self.direction == 1){ mobile_menu.play(); } } } });
    5 points
  19. let explodeCont = document.querySelectorAll('.anim-explode-container'); explodeCont.forEach((container) => { let svg = container.querySelector('.anim-explode'); let shapes = [ 'M254 286.11a50 50 0 0050-50H204a50 50 0 0050 50z', 'M255.5 271a20 20 0 10-20-20 20 20 0 0020 20zm0 30a50 50 0 10-50-50 50 50 0 0050 50z', 'M307.5 250a50 50 0 11-50-50 50 50 0 0150 50', 'M234 237a22.5 22.5 0 0045 0h27.5a50 50 0 01-100 0z', 'M258 202.5a12 12 0 00-12 12v26h-26a12 12 0 000 24h26v26a12 12 0 0024 0v-26h26a12 12 0 000-24h-26v-26a12 12 0 00-12-12z', ]; container.addEventListener('mouseenter', (e) => { let animatedShapes = []; for (var i = 0; i < 10; i++) { let newElement = document.createElementNS( 'http://www.w3.org/2000/svg', 'path' ); newElement.setAttribute('d', gsap.utils.random(shapes)); newElement.style.fill = gsap.utils.random([ '#4899DF', '#f0f0f0', '#00C0CC', '#DE2870', '#C7DBF4', ]); svg.appendChild(newElement); animatedShapes.push(newElement); } function killShapes() { animatedShapes.forEach((shape) => { svg.removeChild(shape); }); } gsap.set(animatedShapes, { transformOrigin: 'center', scale: 'random(0.2, 1)', }); gsap.to(animatedShapes, { onComplete: killShapes, keyframes: [ { rotate: 'random(180, -180)', x: 'random([-150, -100, -200, 200, 100, 150])', y: 'random([-150, -100, -200, 200, 100, 150])', ease: 'expo.out', duration: 4, stagger: { amount: 0.1, }, }, { opacity: 0, delay: -3 }, ], }); }); }); Apologies for the wall of code - but I did a similar thing on this site for the tickets button up at the top right. Might be helpful to see another approach. It's using SVG which is quite nice for responsive/crisp vector stuff (I'll try to loop back and pop this in a codepen next week, but I have sunday roast and wine waiting right now πŸ‘€)
    5 points
  20. Hey there @Dipit Maurya I'd probably work with a data-attribute on each .inner-listing for something like that. Maybe something like this: https://codepen.io/akapowl/pen/c95cfa7260c37ea092daef8f5c92fd13 Edit: ... here is another version, polished up a bit with regard to margins/padding and a slight change on the start/end of the ScrollTrigger. https://codepen.io/akapowl/pen/d4b4927ba6227d308fb947c1cf4f388d
    5 points
  21. Here you go @Catalin R. What is important, is to make sure that you still specifically set the body as the scroller and the pinType to "transform" - I did it here via ScrollTrigger.defaults(). Just as a little sidenote: You are actually applying a third-party smooth-scrolling library to work on the body - and then hooking up ScrollTrigger to that smooth-scroll via the .scrollerProxy(). https://codepen.io/akapowl/pen/16d802e8f90b1795ca1b86e2da67232a
    5 points
  22. Hi @rala , welcome to the forum! πŸ’š GSAP has been in the market for a long time and has lots of tutorials (free and paid) and also you can find more stuff inside the forums. If you want to start some courses I can recommend these ones: https://www.creativecodingclub.com/ https://www.motiontricks.com/ And to learn more about the effects you were looking you can go to the forum, for example: Hope this helps and if you have any issue you can ask on the forum providing a minimal demo and we'll help you! πŸ™Œ
    5 points
  23. Try this: onLeave: function(self) { self.scroll(self.start); // <-- sets position to start of ScrollTrigger self.disable() self.animation.progress(1) } https://codepen.io/akapowl/pen/2f164f6fc6ea04ad8480421d9b3cd011
    5 points
  24. New version of CreateJS came out then, so you need to specify the updated CDN link in your head. OLD to replace: <script src="https://code.createjs.com/createjs-2015.11.26.min.js"></script> NEW: <script src="https://code.createjs.com/1.0.0/createjs.min.js"></script> Or via Google's CDN > <script src="https://s0.2mdn.net/ads/studio/cached_libs/createjs_2019.11.15_min.js"></script> Once updated, should work fine.
    5 points
  25. Welcome to forums @rsheppard Animating a CSSRule will apply to all pseudo elements that use that rule. You should use CSS variables instead. Also, never use CSS transitions on properties that you are animating with GSAP. Using all, applies to all properties, so it will mess up your GSAP animations. GSAP Underline Animation (codepen.io)
    5 points
  26. Here are some notes on that; You are initially creating a tween (scrollTween) on all sections and then again in the forEach loop also create a tween for each individual section. You shouldn't do that - in the fake-pinning example the only tweens created are in the forEach loop When checking if an element has a class, don't include the leading '.' // bad thumb.classList.contains('.fakePin') // good thumb.classList.contains('fakePin') You forgot to change the container variable in the individual tweens to mainContainer - a container variable doesn't exist in your example. There are no margins on your panels, but instead you are making use of the grid-column-gap, so instead of the marginRight of the element that is being considered in the getTotalWidthToMove() function, you will have to get the gridColumnGap of the parent. I also made some changes to the CSS in this following example, so you might need to consider addapting that for things to work properly https://codepen.io/akapowl/pen/db4c5133bf37a7f617fceda56f94c8dc
    5 points
  27. Heya Hannah! You can use invalidate() in this sort of situation. .invalidate( ) : self [override] Flushes any internally-recorded starting/ending values which can be useful if you want to restart an animation without reverting to any previously recorded starting values. https://codepen.io/GreenSock/pen/abwMweQ?editors=0011
    5 points
  28. Hello there @qvstudio. You can set an endalongside an endTrigger. With the endTrigger you can target the section you want the end to trigger on and with the end you can define at which point in the viewport for that section the ScrollTrigger is supposed to end. https://codepen.io/akapowl/pen/b21e2d07d0ec48b8490d86945e66f4b0 From the ScrollTrigger docs: endTrigger String | Element - The element (or selector text for the element) whose position in the normal document flow is used for calculating where the ScrollTrigger ends. You don't need to define an endTrigger unless it's DIFFERENT than the trigger element because that's the default.
    5 points
  29. For the lines that are supposed to be moving to the right, you will likely have to make sure that they start with their right side against the right side of the window (which is basically where you are tweening the other one to); so I would probably make use of a fromTo tween for that, with which you can declare their starting position in the from part - something like I did in this horizontal-scrolling example. https://codepen.io/akapowl/pen/dyvygmj That pen creates a ScrollTrigger forEach of the 'sections' - which can give you a bit more control. Here's what that could look like with your example https://codepen.io/akapowl/pen/a5e95c5b1cafbdc1d8d12d58a030407e
    5 points
  30. Sounds like you're using it correctly. It's just a visual aide to help people understand how shapeIndex works, no drag and drop or complexity to it. You can use CSS to position your SVG differently if you need to? https://codepen.io/GreenSock/pen/qBjQmKJ Yes, you can omit it. shapeIndex is just an option - if auto works you don't have to specify anything. It will default to auto. Sounds like learning to code! It takes a long time to build up all the little bits of satellite knowledge and then the strings to connect them. It shouldn't be a 'major bummer' though. Especially seeing as you're learning to animate a fish... Compared to a lot of things you have to learn in this industry animating fish is definitely on the fun side of things! Don't be so hard on yourself, everyone starts off not understanding anything. We've all been here. Just take it slowly.
    5 points
  31. It looks like GSAP is setting the overflow when you resize, so you can just change it again onRefresh... A Pen by GreenSock (codepen.io)
    4 points
  32. I fiddled around with it a bit and found it worked best to tween on / set the groups instead of the paths - just had to make sure every group inside the #bounce had a background rect - as i found it worked this way, I didn't look further if there was a better solution - but it works and looks quite easy. https://codepen.io/akapowl/pen/a3134b964c569b9fffead620eb78cec7
    4 points
  33. Hey there sarathchand19, Welcome to the forums. πŸ₯³ This sounds like a z-index issue. I'd recommend making sure the s-i element is actually able to be hovered and not being blocked by other elements on top of it. This won't be down to GSAP itself, but a side effect of whatever styling you've applied. It's not possible to help any further without seeing a codepen or codesandbox demo though I'm afraid. I hope this helps point you in the right direction
    4 points
  34. Hello @flim Is there any particular reason you need the tween to be in the onEnter callback? If you need to stick to the .create() method (vs adding a scrollTrigger to that tween itself - the commented out part in below example) you could just hook up a tweeen or timeline via ScrollTrigger's animation property. https://codepen.io/akapowl/pen/00ec094aec7abe63df27789734f88186
    4 points
  35. Hey there welcome to the forums! This is an easy thing to get confused by. You're looking for a loop. https://codepen.io/GreenSock/pen/eYENLLw This article is a good read if you want to avoid common mistakes
    4 points
  36. Also - there's a difference between a path that *is* a stroke, and a path *with* a stroke. https://codepen.io/svganimationworkshop/pen/oNegWGy
    4 points
  37. Welcome to the forums @dve46 I would put a wrapper element around the canvas and use that instead since the inline styling that GSAP is apply for the pinning is not going to match the attributes that three.js sets. ScrollTrigger Pinning with three.js (codepen.io)
    4 points
  38. Hey there @animationmagic By disabling the first ScrollTrigger onLeave and thus removing the pinSpacer, you are changing the height of the document and since that second ScrollTrigger's start will be set when the pinSpacer of the first ScrollTrigger is still there, you would actually have to call a ScrollTrigger.refresh() after disabling the first ScrollTrigger, so the start of the second ScrollTrigger can be set again to its now correct value. Usually you'll just want to wrap all your content inside a wrapper and pin that wrapper if you don't want any pin-spacing to be visible in cases as such. Now in your scenario with the first ScrollTrigger that is being disabled onLeave things will be sort of tricky if you wrapped all the content, so I'd suggest just wrapping the portion of content after that first section you are pinning individually before in a wrapper and pin that. Something like this: https://codepen.io/akapowl/pen/8c708012c35eff9fc01c5b89265d7a0d Please note though, that if you will add any subsequent ScrollTriggers on elements inside that .second-pin wrap, you will likely have to specify that wrap within the pinnedContainer property on those subsequent ScrollTriggers, as they can not take any pinSpacing into account because they will be within that wrap. I hope that's helpful, happy scrolling!
    4 points
  39. Hi Deepus, We added directional snapping in 3.8 which seems to have affected this demo. I've set directional to false and it's behaving as expected now. https://codepen.io/GreenSock/pen/bGexQpq
    4 points
  40. Welcome to the forums @felipejorge You should check out this blog post for 3.7. There are some demos that do exactly that. https://codepen.io/GreenSock/pen/RwpBOvR https://codepen.io/GreenSock/pen/OJpwYXO
    4 points
  41. What was wrong with using the onComplete callback? It shouldn't be too hard to figure out the index of the element that is snapped. Some pseudo code. snap: { snapTo: 1 / 33, duration: 0.5, onComplete: (scrollTrigger )=> { let index = Math.round(scrollTrigger.progress * 33); let currentElement = arrayOfMyElements[index]; } },
    4 points
  42. Hey @animationmagic You could e.g. use the onLeave callback of the ScrollTrigger to disable the ScrollTrigger (which would be neccessary to get rid of the white space added by the pin-spacer) and force the hooked-up animation's progress to 1. Does something like this work better for you? https://codepen.io/akapowl/pen/98d4cdb407420d290296bce2affc5c6b
    4 points
  43. Hi Charlyta, The attached demo is quite complex. We ask for minimal demos here to make it easier to parse and help find a solution. Maybe this demo will help, or at least serve as a good starting point to figure out the logic you need. https://codepen.io/GreenSock/pen/mdwZBGW I also noticed that you're using deprecated syntax. Check out the migration guide here. https://greensock.com/3-migration/
    4 points
  44. https://codepen.io/GreenSock/pen/PojvmMa?editors=0011 Hmm. Well you don't have to use a stagger, you could target specific items in the array? Feels a bit fragile though. I'd probably rather get rid of the spans and add coloured full stops with pseudo elements.
    4 points
  45. Hi @rsheppard Welcome to the forum. I don't think that'll work correctly since you're targeting the rule. I'd probably just loop through and add some real DOM elements. https://codepen.io/PointC/pen/37cfe9e3ace3288e866a771c96526fcf Happy tweening.
    4 points
  46. Hey Aki-sol, The x-axis animation needs to have a linear ease applied ease:'none' in order to snap to the correct points - otherwise the progress of the animation over time will be unevenly distributed (according to the ease applied) I'm not sure why you have adjusted the xPercent value to -90, but that also needs to be 100 - aka 100% of the elements width https://codepen.io/GreenSock/pen/oNwJOKw?editors=1010
    4 points
  47. Hey @PG1 that is because Chrome blocks the audio if the user didn't interact with something in the page. You need to add a button or any action so the user can interact on the page before your animation. You can check this if you click on the page before your animation begin. To avoid audio errors you can go here. πŸ™‚
    4 points
  48. Hi Aki-sol, That looks to me like a standard image scale. You can just say scale:1.4 That will use a transform. There's a list of properties you can use in this article -
    4 points
Γ—