Jump to content
Search Community

ScrollTrigger to trigger background color change

clieee test
Moderator Tag

Recommended Posts

Hi,

 

I have a page where I have x number of containers/divs. Some of these have defined background colors, and should thereby change body background color once they getting visible as you scroll down. But also change back to their color if user scrolls back up.

 

I'm using React and my thought was to create a custom hook that I connect to the node/container/div that should be used as trigger. That is all working fine, if that seems to be a good approach, I basically create a new ScrollTrigger every time that hook is being used.

 

However, some questions:

- I guess I have to use the callbacks for onEnter and onEnterBack in order to add/remove the body background color class?

- What should my start values be? "top top" (=if top of element hits top of viewport) if a "colored" section is a top of page? And for other sections "top bottom" (=if top of element reaches bottom of viewport)?

- If the first section on the page should set a specific background color, and then the user scrolls down a bit, the next section becomes visible = trigger color change, but then the user scrolls back up again, how can I tell if it should transition back to it's color again then? onEnterBack wont get triggered in this case..?

Link to comment
Share on other sites

1 hour ago, clieee said:

I guess I have to use the callbacks for onEnter and onEnterBack in order to add/remove the body background color class?

Sure, that works. Or you could animate the backgroundColor directly (not use classes).

 

1 hour ago, clieee said:

What should my start values be? "top top" (=if top of element hits top of viewport) if a "colored" section is a top of page? And for other sections "top bottom" (=if top of element reaches bottom of viewport)?

That makes sense. It depends on when you want it to happen :) 

 

1 hour ago, clieee said:

If the first section on the page should set a specific background color, and then the user scrolls down a bit, the next section becomes visible = trigger color change, but then the user scrolls back up again, how can I tell if it should transition back to it's color again then? onEnterBack wont get triggered in this case..?

It'd probably make more sense to use the onEnter and onLeaveBack for this sort of thing. You can save the colors to a list and use that.

 

I did this same sort of thing in this thread (without React):

This thread is very similar as well:

 

  • Like 3
Link to comment
Share on other sites

  • 1 year later...

guys, can you help me?
I want to change the background color when I click

I use the code: 

gsap.utils.toArray(".section").forEach(function (elem) {

    var color = elem.getAttribute('data-color');

    ScrollTrigger.create({
        trigger: elem,
        start: 'top 30%',
        end: 'bottom 30%',
        markers: false,
        onEnter: () => gsap.to('main', {
            backgroundColor: color,
            duration: 1.4
        }),
        onLeave: () => gsap.to('main', {
            backgroundColor: '#fef9ef',
            duration: 1.4
        }),
        onLeaveBack: () => gsap.to('main', {
            backgroundColor: '#fef9ef',
            duration: 1.4
        }),
        onEnterBack: () => gsap.to('main', {
            backgroundColor: color,
            duration: 1.4
        }),
    });
});


this is to change the background color when switching to another section

Now I want to use simple code: 

const elem = document.querySelector(".section.hero");
const switcher = document.querySelector(".switch-theme");

switcher.addEventListener('click', function() {
  if (elem.hasAttribute == ('data-color', "#FEF9EF") {
    this.setAttribute = ('data-color', "#000000");
  }
});

To click on the element to change the color of my section, but I get an error instead

Is it possible to change the data-color dynamically somehow?

 

Link to comment
Share on other sites

This is definitely wrong:

// BAD
if (elem.hasAttribute == ('data-color', "#FEF9EF") {
  this.setAttribute = ('data-color', "#000000");
}

// GOOD (maybe? I'm not sure what your intent is)
if (elem.getAttribute('data-color') === "#FEF9EF") {
  elem.setAttribute('data-color', "#000000");
}

You could also simplify your ScrollTrigger:

// OLD
ScrollTrigger.create({
  trigger: elem,
  start: 'top 30%',
  end: 'bottom 30%',
  markers: false,
  onEnter: () => gsap.to('main', {
    backgroundColor: color,
    duration: 1.4
  }),
  onLeave: () => gsap.to('main', {
    backgroundColor: '#fef9ef',
    duration: 1.4
  }),
  onLeaveBack: () => gsap.to('main', {
    backgroundColor: '#fef9ef',
    duration: 1.4
  }),
  onEnterBack: () => gsap.to('main', {
    backgroundColor: color,
    duration: 1.4
  }),
});


// NEW
ScrollTrigger.create({
	trigger: elem,
	start: 'top 30%',
	end: 'bottom 30%',
	onToggle: (self) => gsap.to('main', {
		backgroundColor: self.isActive ? color : '#fef9ef',
		duration: 1.4
	})
});

If you need more help, please provide a minimal demo in CodePen or something like that. 

 

Happy tweening!

Link to comment
Share on other sites

On 1/16/2022 at 1:07 AM, OSUblake said:

Hi @GeorgeErshov

 

Can you create a new topic with your question and include a minimal demo? Thanks!

 

Hi, sorry it took so long

Here's a simple demonstration. I want to click-me button (class='change-color') to change the color of all sections that have data-color, to a different color (the designer came up with a dark theme)
 

See the Pen RwLXmwB by GeorgeDesign2020 (@GeorgeDesign2020) on CodePen

Link to comment
Share on other sites

14 hours ago, OSUblake said:

Привет Джордж,

 

Я все еще не уверен, что вы пытаетесь сделать. У вас есть код ScrollTrigger, который меняет фон, но теперь вы говорите, что хотите, чтобы кнопка менялась на фон, так что же это?

I want to change the attributes of the sections by clicking on this button, I want the data-color to change

For example: class='section s-1' has data-color='#838C8B'.
By clicking on the button, I want to change the data-color='#000000'
make the background black, and in the section class='section s-2' make the data-color='#ffffffff'

Here's the site I'm working on, here the designer wants me to change the colors to contrasting (black and white) for the visually impaired when I click on the eye

https://function-x-siberia-site.webflow.io/

 

 

Снимок экрана 2022-01-25 в 11.25.21.png

Link to comment
Share on other sites

Hi George! 

 

You haven't got any logic in place for the button at all. What have you tried so far?

 

You'll likely need to toggle a boolean like so.

 

let contrastMode
button.addEventListener(click, (e) => {
 contrastMode = !contrastMode;
  
 if(contrastMode) {
   // make sections black and white
 } else {
   // make sections original colors
 }
})

 

If you give it a go we can help to nudge you in the right direction, but unfortunately we don't offer free custom solutions in these forums.

 

The GSAP part would be similar to what you have here already - just a tween that changes color. The tricky bit will be the logic of what happens with the scrollTrigger when the state changes - if you need scrollTriggered sections that change color too you'll need to use variables for the colors, update them in your logic loop and call scrollTrigger.refresh() to update the values
 

 

  • Like 2
Link to comment
Share on other sites

7 hours ago, Cassie said:

Hi George! 

 

You haven't got any logic in place for the button at all. What have you tried so far?

 

You'll likely need to toggle a boolean like so.

 

let contrastMode
button.addEventListener(click, (e) => {
 contrastMode = !contrastMode;
  
 if(contrastMode) {
   // make sections black and white
 } else {
   // make sections original colors
 }
})

 

If you give it a go we can help to nudge you in the right direction, but unfortunately we don't offer free custom solutions in these forums.

 

The GSAP part would be similar to what you have here already - just a tween that changes color. The tricky bit will be the logic of what happens with the scrollTrigger when the state changes - if you need scrollTriggered sections that change color too you'll need to use variables for the colors, update them in your logic loop and call scrollTrigger.refresh() to update the values
 

 

Hi, yes i already tried to do different things with both jquery and javascript
Please look now, I added some very simple code

$('.change-color').click(function() {
  $("#id").attr("data-color","#000000"); 
  console.log('change dark-mode');
  scrollTrigger.refresh()
})

 

 

See the Pen RwLXmwB by GeorgeDesign2020 (@GeorgeDesign2020) on CodePen

 

But nothing happens, I seem to be calling the scrolltrigger.refresh() method incorrectly

Link to comment
Share on other sites

Hi George,

 

This is will be only read 1 time. That's just how JavaScript works.

 

var color = elem.getAttribute('data-color');

 

If you need it to update, you're going to have to provide a way to update the value inside of the forEach. I just used map to create an array of functions that will update the color value and set the background if the trigger is active.

 

See the Pen mdqdqNV by GreenSock (@GreenSock) on CodePen

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

  • 2 years later...

What if I have:

- Many sections

- Only some of them change background color

- I just want to target each sections

 

If you see this demo 

See the Pen PogOQQr by fernandocomet (@fernandocomet) on CodePen

 

First two are ok, but I am changing the color to all classes with naming "sectiontrigger". What if I just want to target the current section on the viewport?

What is the best approach? 

Link to comment
Share on other sites

Oh sorry and thanks Rodrigo.

 

The issue I have is that if I apply the transformation to class "sectiontrigger", all sections with that class change their color. 

So I just want to change the color of each one when the user reachs them, but keeping their color when not. 

 

So I have these sections, defining background Color initially:

.hero{ background-color: MediumSeaGreen; }
.s1{ background-color: SlateBlue; }
.s3{ background-color: DodgerBlue; }
.s5{ background-color: tomato; }
.s7{ background-color: gold; }

 

I just want to change the color of these sections  to their "data-color" attribute 

  <section data-color='#FF6347' class='section sectiontrigger'>Section 1</section>
  <section class='section'>Section 2</section>
  <section data-color='#7FFF00' class='section sectiontrigger'>Section 3</section>
  <section class='section'>Section 4</section>
  <section data-color='#00FFFF' class='section sectiontrigger'>Section 5</section>
  <section class='section'>Section 6</section>
  <section data-color='#FF7F50' class='section sectiontrigger'>Section 7</section>
  <section class='section'>Section 8</section>

 

But I want to keep the initial color (when the ScrollTrigger is not active), so the change should not affect all sections

 

Doing as many scrollTriggers as sections I want to change is not a good approach.  

Link to comment
Share on other sites

No problemo, Mondays are always tough:

27f85acd89b14b3c1347d61352470587.jpg

Actually creating a ScrollTrigger instance for each section is a good approach actually, I think you're just overcomplicating this a bit. Just use a single GSAP Tween controlled with ScrollTrigger toggle actions:

const sections = gsap.utils.toArray(".sectiontrigger");

sections.forEach(function (section, i) {
  var color = section.getAttribute("data-color");
  
  gsap.to(section, {
    backgroundColor: color,
    ease: "power1.inOut",
    scrollTrigger: {
      trigger: section,
      start: "top 50%",
      end: "bottom 95%",
      markers: true,
      toggleActions: "play none none reverse",
    },
  });
});

Here is the updated demo:

See the Pen XWQzYaR by GreenSock (@GreenSock) on CodePen

 

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

That looks good Rodrigo

 

Thanks a lot

 

I am experimenting right now with Glaze, so it is GSAP + Data Attributes.

Some NoCode tools use this approach 

 

See here

See the Pen bGJYXJO by fernandocomet (@fernandocomet) on CodePen

 

 

What is the correct approach if I want Section 1 to disappear when it is out of the viewport, and if the User comes again repeat the animation?

 

Not sure if I should touch something on ToggleActions or better in the ScrollTrigger Start/Stop settings. 

 

For ToggleActions (onEnter, onLeave, onEnterBack, onLeaveBack)

I have: [play_reverse_play_reverse]

 

For ScrollTrigger settings I have:

start-[top_50%]

end-[bottom_95%]

Link to comment
Share on other sites

Hi,

 

I'm not sure I follow 100% what you're trying to  do but maybe something like this:

See the Pen YzMYJMJ by GreenSock (@GreenSock) on CodePen

 

That's the approach I would follow in order to show/hide an element that has the height of the viewport, based on it's position in the viewport. Keep in mind that end: "bottom 95%" means that the ScrollTrigger end point will be at almost the bottom of the viewport (95%, with the top being 0%) and the bottom of the element will hit that almost immediately after the top passes the top of the viewport.

 

Here is what the ScrollTrigger docs have about start, end and toggleActions:

start
String - Describes a place on the trigger and a place on the scroller that must meet in order to start the ScrollTrigger. So, for example, "top center" means "when the top of the trigger hits the center of the scroller" (and the scroller is the viewport by default). "bottom 80%" means "when the bottom of the trigger hits 80% down from the top of the viewport" (assuming vertical scroll). You can use keywords like "top", "bottom", "center" (or "left" and "right" if horizontal: true) or percentages like "80%" or pixel values like "100px". Percentages and pixels are always relative to the top/left of the element/scroller. You can even use a complex relative value like "top bottom-=100px" which means "when the top of the trigger hits 100px above the bottom of the viewport/scroller"

 

end

String - Describes a place on the endTrigger (or trigger if one isn't defined) and a place on the scroller that must meet in order to end the ScrollTrigger. So, for example, "bottom center" means "when the bottom of the endTrigger hits the center of the scroller". "center 100px" means "when the center of the endTrigger hits 100px down from the top of the scroller" (assuming vertical scroll). You can use keywords like "top", "bottom", "center" (or "left" and "right" if horizontal: true) or percentages like "80%" or pixel values like "100px". Percentages and pixels are always relative to the top/left of the element/viewport. You can also define a single relative value like "+=300" which means "300px beyond where the start is", or "+=100%" means "the height of the scroller beyond where the start is". "max" is a special keyword indicating the maximum scroll position.

 

toggleActions
String - Determines how the linked animation is controlled at the 4 distinct toggle places - onEnter, onLeave, onEnterBack, and onLeaveBack, in that order. The default is play none none none. So toggleActions: "play pause resume reset" will play the animation when entering, pause it when leaving, resume it when entering again backwards, and reset (rewind back to the beginning) when scrolling all the way back past the beginning. You can use any of the following keywords for each action: "play", "pause", "resume", "reset", "restart", "complete", "reverse", and "none".

 

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

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...