Jump to content
Search Community

Using ScrollTrigger with an Array of Objects

kittbunney

Go to solution Solved by Rodrigo,

Recommended Posts

Posted

Hey, this is my first post so I hope I've done the codepen thing right - 

 

I have a question about accessing values from inside a map. My goal is that as you scroll past a specific HTML element, which has an animation applied to it, it will also change another HTML element to a specific value held inside an array of objects. The way I have it set up so far is that the HTML elements are all contained within that same object, and I would like the gsap animation to look at the key of the object it's just scrolled past (in this case: 'role') and get the 'skill1' value from that same object to change the width of the skill slider.

 

Hopefully you can see from my codepen that the 'skill2' slider changes to the fixed value of 90% each time it scrolls past a new 'role'. But I would like it to change to the 'skill' value held within the object. My attempt at doing so with the 'skill1' slider has not been successful. Any suggestions?

 

Cheers, Kitt

 

UPDATE!

I figured it out! If anyone else would benefit from knowing how I solved this, the updated codepen is below - 

 

I took the innerHTML from the DOM element that was created by the array of objects that I was referencing and used it to search that same array for the skill value I needed, which I then assigned to a variable that could be referenced when I needed that value later in the animation. I hope that makes sense.

 

Happy times :)

 

 

See the Pen EaVNjMm by kittbunney (@kittbunney) on CodePen.

  • kittbunney changed the title to Using ScrollTrigger with an Array of Objects
  • Solution
Posted

Hi @kittbunney and welcome to the GSAP Forums!

 

Maybe you're trying to do something like this:

See the Pen YPyppzZ by GreenSock (@GreenSock) on CodePen.

 

Just use one array for all the skill elements slides that need animated and then just use an array with all the values in order to match them easier. If you need some other value besides the width value, you can create an array of objects, like this:
 

const data = [
  {
    role: "Design & Art Direction",
    values: [
      { skill: "Skill One", value: 90 },
      { skill: "Skill Two", value: 75 },
      { skill: "Skill Three", value: 60 },
      { skill: "Skill Four", value: 95 },
      { skill: "Skill Five", value: 100 },
    ],
    idn: "001"
  },

  {
    role: "Multimedia Designer",
    values: [
      { skill: "Skill One", value: 25 },
      { skill: "Skill Two", value: 80 },
      { skill: "Skill Three", value: 60 },
      { skill: "Skill Four", value: 70 },
      { skill: "Skill Five", value: 20 },
    ],
    idn: "002"
  }
];

You can target them like this:

const titles = gsap.utils.toArray(".jobtitle");
const skills = gsap.utils.toArray(".combiskills .skillsinfront");

titles.forEach((title, i) => {
  const dataTarget = data[i];
  const skills = data[i].skills;

  gsap
    .timeline({
    scrollTrigger: {
      trigger: title,
      start: "top 80%",
      end: "top 20%",
      scrub: true,
      immediateRender: i < 1,
      markers: true
    }
  })
    .to(skills.toReversed(), {
    width: (j) => skills[j].value + "%",
    stagger: 0.1
  });
});

Here is a fork of the previous demo using this approach:

See the Pen gbaLLpo by GreenSock (@GreenSock) on CodePen.

 

Hopefully this helps

Happy Tweening!

Posted
9 hours ago, Rodrigo said:

Just use one array for all the skill elements slides that need animated and then just use an array with all the values in order to match them easier. If you need some other value besides the width value, you can create an array of objects, like this:
 

const data = [
  {
    role: "Design & Art Direction",
    values: [
      { skill: "Skill One", value: 90 },
      { skill: "Skill Two", value: 75 },
      { skill: "Skill Three", value: 60 },
      { skill: "Skill Four", value: 95 },
      { skill: "Skill Five", value: 100 },
    ],
    idn: "001"
  },

  {
    role: "Multimedia Designer",
    values: [
      { skill: "Skill One", value: 25 },
      { skill: "Skill Two", value: 80 },
      { skill: "Skill Three", value: 60 },
      { skill: "Skill Four", value: 70 },
      { skill: "Skill Five", value: 20 },
    ],
    idn: "002"
  }
];

You can target them like this:

const titles = gsap.utils.toArray(".jobtitle");
const skills = gsap.utils.toArray(".combiskills .skillsinfront");

titles.forEach((title, i) => {
  const dataTarget = data[i];
  const skills = data[i].skills;

  gsap
    .timeline({
    scrollTrigger: {
      trigger: title,
      start: "top 80%",
      end: "top 20%",
      scrub: true,
      immediateRender: i < 1,
      markers: true
    }
  })
    .to(skills.toReversed(), {
    width: (j) => skills[j].value + "%",
    stagger: 0.1
  });
});

 

@Rodrigo That's such an elegant and versatile solution, thank you so much!

Definitely a lot better than my workaround, and with way more flexibility for add more skills without having to add a lot more code in. Beautiful!

 

Have a lovely day 🤗

  • Like 1

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...