Share Posted November 29, 2022 Hi, I have encountered a question. How can I animate even or odd Columns (Rows) with the help of the GSAP to library? P.S: I don't know how to target the imaginery columns! :)) I know the rest ... See the Pen oNyMJQQ by emdesigner-or (@emdesigner-or) on CodePen Link to comment Share on other sites More sharing options...
Share Posted November 29, 2022 Hey there! There's not really a specific way to target grid elements based on their position. You can use the nth-child selector to target specific elements. What are your limitations here? Could you add a class? Do you know how many rows or columns there will be? See the Pen YzvOzpN by GreenSock (@GreenSock) on CodePen 1 Link to comment Share on other sites More sharing options...
Solution Solution Share Posted November 30, 2022 This was a fun chance for me to whip up a helper function that lets you dynamically figure out the rows/columns as well as further refine those with "odd" or "even" ones: function getGrid(selector) { let elements = gsap.utils.toArray(selector), bounds, getSubset = (axis, dimension, alternating, merge) => { let a = [], subsets = {}, onlyEven = alternating === "even", p; bounds.forEach((b, i) => { let position = Math.round(b[axis] + b[dimension] / 2), subset = subsets[position]; subset || (subsets[position] = subset = []); subset.push(elements[i]); }); for (p in subsets) { a.push(subsets[p]); } if (onlyEven || alternating === "odd") { a = a.filter((el, i) => !(i % 2) === onlyEven); } if (merge) { let a2 = []; a.forEach(subset => a2.push(...subset)); return a2; } return a; }; elements.refresh = () => bounds = elements.map(el => el.getBoundingClientRect()); elements.columns = (alternating, merge) => getSubset("left", "width", alternating, merge); elements.rows = (alternating, merge) => getSubset("top", "height", alternating, merge); elements.refresh(); return elements; } Usage: let grid = getGrid(".grid-i"), // first get the grid which is actually an Array of all the elements rows = grid.rows(), // all rows evenRows = grid.rows("even"), // just the even ones oddColumns = grid.columns("odd"); // just the odd columns It returns an Array with an Array for each column/row. You can even pass in true as the 2nd parameter to have it merge them all into a flat Array. Demo: See the Pen KKexgWp?editors=0010 by GreenSock (@GreenSock) on CodePen I hope that's useful. 3 1 Link to comment Share on other sites More sharing options...
Share Posted November 30, 2022 Jack casually swinging in with the big guns 💪✨ 1 Link to comment Share on other sites More sharing options...
Author Share Posted November 30, 2022 12 hours ago, GreenSock said: This was a fun chance for me to whip up a helper function that lets you dynamically figure out the rows/columns as well as further refine those with "odd" or "even" ones: function getGrid(selector) { let elements = gsap.utils.toArray(selector), bounds, getSubset = (axis, dimension, alternating, merge) => { let a = [], subsets = {}, onlyEven = alternating === "even", p; bounds.forEach((b, i) => { let position = Math.round(b[axis] + b[dimension] / 2), subset = subsets[position]; subset || (subsets[position] = subset = []); subset.push(elements[i]); }); for (p in subsets) { a.push(subsets[p]); } if (onlyEven || alternating === "odd") { a = a.filter((el, i) => !(i % 2) === onlyEven); } if (merge) { let a2 = []; a.forEach(subset => a2.push(...subset)); return a2; } return a; }; elements.refresh = () => bounds = elements.map(el => el.getBoundingClientRect()); elements.columns = (alternating, merge) => getSubset("left", "width", alternating, merge); elements.rows = (alternating, merge) => getSubset("top", "height", alternating, merge); elements.refresh(); return elements; } Usage: let grid = getGrid(".grid-i"), // first get the grid which is actually an Array of all the elements rows = grid.rows(), // all rows evenRows = grid.rows("even"), // just the even ones oddColumns = grid.columns("odd"); // just the odd columns It returns an Array with an Array for each column/row. You can even pass in true as the 2nd parameter to have it merge them all into a flat Array. Demo: I hope that's useful. Thanks a lot!!! Link to comment Share on other sites More sharing options...
Share Posted February 8 On 11/30/2022 at 6:38 AM, GreenSock said: This was a fun chance for me to whip up a helper function that lets you dynamically figure out the rows/columns as well as further refine those with "odd" or "even" ones: function getGrid(selector) { let elements = gsap.utils.toArray(selector), bounds, getSubset = (axis, dimension, alternating, merge) => { let a = [], subsets = {}, onlyEven = alternating === "even", p; bounds.forEach((b, i) => { let position = Math.round(b[axis] + b[dimension] / 2), subset = subsets[position]; subset || (subsets[position] = subset = []); subset.push(elements[i]); }); for (p in subsets) { a.push(subsets[p]); } if (onlyEven || alternating === "odd") { a = a.filter((el, i) => !(i % 2) === onlyEven); } if (merge) { let a2 = []; a.forEach(subset => a2.push(...subset)); return a2; } return a; }; elements.refresh = () => bounds = elements.map(el => el.getBoundingClientRect()); elements.columns = (alternating, merge) => getSubset("left", "width", alternating, merge); elements.rows = (alternating, merge) => getSubset("top", "height", alternating, merge); elements.refresh(); return elements; } Usage: let grid = getGrid(".grid-i"), // first get the grid which is actually an Array of all the elements rows = grid.rows(), // all rows evenRows = grid.rows("even"), // just the even ones oddColumns = grid.columns("odd"); // just the odd columns It returns an Array with an Array for each column/row. You can even pass in true as the 2nd parameter to have it merge them all into a flat Array. Demo: I hope that's useful. @GreenSock How do I use this but with a scrolltrigger? I need to animate items per row, but it seems that when I use the row as a trigger it doesn't work. This is what I added to it: ``` rows.forEach((GridItems) => { let tl = gsap.from(GridItems, {opacity: 0, yPercent: 80, stagger: 0.05, duration: 0.7, overwrite: true}); ScrollTrigger.create({ trigger: GridItems, start: 'top 70%', end: 'bottom bottom', markers: true, onEnter: () => tl.play(), onEnterBack: () => tl.restart(), onLeaveBack: () => tl.pause(0), }); }); Link to comment Share on other sites More sharing options...
Share Posted February 8 Hi, Using the original example Jack created it should be as simple as this: See the Pen BaPeYdM by GreenSock (@GreenSock) on CodePen Hopefully this helps. If you keep having issues please remember to include a minimal demo of what you have. Happy Tweening! 1 Link to comment Share on other sites More sharing options...
Share Posted February 8 Hi @Rodrigo, thanks for the response! This code works great, but only when you have the full grid displayed in the viewport. When you have a long grid that not fully fits the viewport, the animation shouldn't play on the elements that aren't visible. Only animate those when you scroll to the element in the viewport. I made a little demo: See the Pen NWBVYqG by indy-meermans (@indy-meermans) on CodePen Link to comment Share on other sites More sharing options...
Share Posted February 8 Hi, Maybe you should take a look at ScrollTrigger's batch method: https://greensock.com/docs/v3/Plugins/ScrollTrigger/static.batch() Here is a live example: See the Pen NWGPxGZ by GreenSock (@GreenSock) on CodePen In the case of your last codepen example it would be as simple as this: gsap.registerPlugin(ScrollTrigger); gsap.set(".grid-i", {y: 50, opacity: 0}); ScrollTrigger.batch(".grid-i", { onEnter: batch => gsap.to(batch, {opacity: 1, y: 0, stagger: 0.15, overwrite: true}), }); Hopefully this helps. Let us know if you have more questions. Happy Tweening! 1 1 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