OSUblake last won the day on
OSUblake had the most liked content!
OSUblake
Moderators-
Posts
9,196 -
Joined
-
Last visited
-
Days Won
708
Content Type
Profiles
Forums
Store
Blog
Product
Showcase
FAQ
Downloads
Everything posted by OSUblake
-
Now if a component has a bunch children elements that you want to animate, you're going to have to get a reference to them somehow. Most common is probably with the useRef. function MySvg() { const svg = useRef(); const circle1 = useRef(); const circle2 = useRef(); const circle3 = useRef(); const rect1 = useRef(); const rect2 = useRef(); const rect3 = useRef(); useEffect(() => { gsap.to([circle1.current, circle2.current, circle3.current], { x: 100 }); gsap.to([rect1.current, rect2.current, rect3.current], { y: 200 }); }, []); return ( <svg ref={svg}> <circle ref={circle1}></circle> <circle ref={circle2}></circle> <circle ref={circle3}></circle> <rect ref={rect1}></rect> <rect ref={rect2}></rect> <rect ref={rect3}></rect> </svg> ); } If we had an option to pass in the context, we could eliminate all those useRefs except for the parent one, and just use query strings, greatly reducing the amount of code. function MySvg() { const svg = useRef(); useEffect(() => { gsap.to("circle", { context: svg.current, x: 100 }); gsap.to("rect", { context: svg.current, y: 200 }); }, []); return ( <svg ref={svg}> <circ></circle> <circ></circle> <circ></circle> <rect></rect> <rect></rect> <rect></rect> </svg> ); }
-
Well, let's first go over the biggest problem I see with React users, they don't use refs. They assume the selector string is just going to target that component, but if you use that component more than once, it's not going to animate correctly. This is supposed to animate the first box to 100 with a color of red, the second box to 200 with a color of green, and the third box to 300 with a color of yellow, but it doesn't happen. https://codepen.io/osublake/pen/581c7a732f60e8322b5b543f4691a77b Correct behavior using refs. https://codepen.io/osublake/pen/b8f05fd1700a1ef0c41ef1c41c9ca0fd
-
How are you using shadow DOM without web components? AFAIK that's the only way.
-
I don't even know how that could work as a default. How would it get a reference to this.shadowRoot? Where I see this being the most helpful is with component frameworks like React. People wouldn't have to contemplate the best way to stagger elements.
-
Yeah, that's probably the worst thing you could do. Why don't you convert that demo over to gsap 3, research how to scale a vector, and then I can provide more guidance. For reference, this is the vector that we want to scale. var point = { x: options.centerX + Math.cos(angle) * options.minRadius, y: options.centerY + Math.sin(angle) * options.minRadius };
-
That's what I'm thinking. So like in React, the user could just pass in the parent element of component. function App() { const container = useRef(null); useEffect(() => { gsap.to(".box", { context: container.current, x: 100 }); }, []); return ( <div className="container" ref={container}> <div className="box"></div> <div className="box"></div> <div className="box"></div> <div className="box"></div> </div> ); }
-
He's saying you don't need to put anything related to GSAP on the data object. The data object is for reactive properties. GSAP animations are not reactive, and therefore you are putting additional overhead into your components by adding your animations to the data object. You can set your animations in any method, mounted, or from the vm passed in. It all points to the same instance. // this isn't needed data() { return {}; }, beforeRouteEnter(to, from, next) { next((vm) => { vm.foo(); console.log(vm.bar); // Hello }); }, // Or using mounted mounted() { this.foo(): console.log(this.bar); // Hello }, methods: { foo() { this.bar = "Hello"; } }
-
Sorry, WordPress n00b here. Isn't there a way to not load the file to begin with?
-
Your mouse image isn't in the DOM when your gsap code runs. You need to put your animation code inside useEffect functions and use refs instead of query strings. Tutorial using ScrollTrigger, but the concepts are still the same. https://edidiongasikpo.com/using-gsap-scrolltrigger-plugin-in-react
-
Don't load your animation code on pages that don't use it.
-
A way to do that more like how Vue handles refs. If a ref attribute appears more than once, it gets added to an array. Ex HTML: <div ref="container"> <div ref="box"></div> <div ref="box"></div> <div ref="box"></div> </div> BaseElement: class BaseElement extends HTMLElement { select(selector) { return this.shadowRoot.querySelectorAll(selector); } createRefs() { const $ = this.$ = {}; for (const node of this.shadowRoot.querySelectorAll("[ref]")) { const id = node.getAttribute("ref"); if (!$[id]) { $[id] = node; } else { if (Array.isArray($[id])) { $[id].push(node); } else { const list = []; list.push($[id], node); $[id] = list; } } } } } Ex JS: class MyComponenet extends BaseElement { connectedCallback() { this.createRefs(); gsap.to(this.$.container, { x: 100 }); gsap.to(this.$.box, { scale: 0.5 }); } }
-
What do you think the API should look like? @GreenSock I think something like this would also be a nice addition, especially for people who use React, Vue, Angular. That way they wouldn't have to create a bunch of refs. But here is how I've handled that in web components. I extend a "BaseElement" class with some extra methods on it. If you're using a library like LitElement, you could do the same thing. class BaseElement extends HTMLElement { select(selector) { return this.shadowRoot.querySelectorAll(selector); } createIdCache() { this.$ = {}; for (const node of this.shadowRoot.querySelectorAll("[id]")) { this.$[node.id] = node; } } } So you would call createIdCache after the DOM is available, like in a connected callback. That will make any elements with an id available on the $ object. Or you could just use the select method. Ex HTML: <div id="container"> <div class="box"></div> <div class="box"></div> <div class="box"></div> </div> Ex JS: class MyComponenet extends BaseElement { connectedCallback() { this.createIdCache(); gsap.to(this.$.container, { x: 100 }); gsap.to(this.select(".box"), { scale: 0.5 }); } }
-
Best place to start is by learning PixiJS, and following some of their examples. Once you get it built, animating the filter is super easy. https://pixijs.io/examples/#/filters-basic/displacement-map-flag.js Examples repo: https://github.com/pixijs/examples Docs: http://pixijs.download/release/docs/index.html
-
Then maybe it's buffering. The canplaythrough event is just an estimate. You might need to download the video. Google how to create a BLOB and use that as a video source. But video is super complicated, and well beyond the scope of this forum. Here's a good place to start learning about all the different properties and events available. https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
-
You should probably be doing .fromTo() animations. Let's say you animate the opacity .from() 0. If that animation gets invalidated when the opacity value is at 0.5, then the new animation will only animate the opacity to 0.5 instead of 1. .from() will always animate to the whatever the value is at that point in time.
-
Horizontal Scroll with Draggable, syncing the two.
OSUblake replied to 17526_1494126625's topic in GSAP
Here's a good example to learn from. https://codepen.io/GreenSock/pen/896549f0a83297debd9111fe9b205a97 -
You really don't need gsap for that. I would just use some delayedCalls. https://codepen.io/osublake/pen/c0e1bc59e2c7779b291c117906cab8f8
-
Performance diff between updating value via timeline vs via onUpdate
OSUblake replied to a-c-sreedhar-reddy's topic in GSAP
The first option should be faster as it has less function calls and object read/writes. Not saying the are no use cases for the second option, but performance isn't one of them. -
I originally made that ripple/wave animation in Pixi, but then I stumbled across a site that showed how SVG filters work basically the same, so it was pretty easy to convert. http://srufaculty.sru.edu/david.dailey/svg/SVGOpen2010/Filters2.htm http://srufaculty.sru.edu/david.dailey/svg/newstuff/Newlist.htm http://srufaculty.sru.edu/david.dailey/svg/texture/texturepage.htm
-
How come I didn't make the list? I've been making SVG waves since 2015. https://codepen.io/osublake/pen/WQyBJb
-
What are you trying to figure out? If you want to animate an list of elements, gsap needs an array or a nodelist. gsap.to([element1, element2, element3], { x: 100 }); Push will just keep adding to that list, so you end up with something like this. gsap.to([element1, element2, element3, element1, element2, element3,element1, element2, element3], { x: 100 }); You can ask the author. It's not necessary. Maybe they did it for clarity. ?♂️
-
Yep. Did you look at the examples in the docs? That's pretty much the format they all use. https://greensock.com/docs/v3/Plugins/ScrollTrigger/static.matchMedia() No that's not possible, but like I said earlier, you can put any code you want inside the matchMedia functions.
-
Sorry, I still don't quite understand what you're asking. You can put whatever code you want into the matchMedia functions. Can you please put what you're trying to achieve into a demo? Media query events don't fire on resize, they fire on media query change events, so trying to debounce them is pointless.