I have this component that every time I change the value of the state I want it to fade between the different colors rather than change straight away how do I do this?
const Header = (props) => {
const [headerColor, setHeaderColor] = useState('#c8e9e6');
useEffect(() => {
document.addEventListener("scroll", () => {
console.log(window.scrollY);
if (window.scrollY < 700) {
setHeaderColor('#c8e9e6');
} else if (window.scrollY >= 700 && window.scrollY < 1500) {
setHeaderColor('#ffae5a');
} else if (window.scrollY >= 500) {
setHeaderColor('#b48fff');
}
});
});
return (
<div className={classes.HeaderContainer} style={{
backgroundColor: headerColor,
}```);
}
You can probably just add a css class the transition by using the property transition & -webkit-transition
For example set the colour to orange after 2 seconds:
.transaition{
background-color: #ffae5a;
-webkit-transition: background-color 2s; /* For Safari 3.1 to 6.0 */
transition: background-color 2s;
}
Related
Im trying to fade in a DIV using opacity when the user gets close to the bottom of the page.
Let's say the page is 3000px high, i want the fade in to start at 2400px and end up completely faded in when the user hits the bottom.
Here is the function i use on the top, but i cant figure out the math i need to get the oposite effect on the bottom of the page...
useEffect(() => {
const handleScroll = event => {
const checkpoint = 500;
const start = 200;
let opacity;
const currentScroll = window.pageYOffset;
if (currentScroll >= start) {
if (currentScroll <= checkpoint) {
opacity = 1 - currentScroll / checkpoint;
} else {
opacity = 0;
}
} else {
opacity = 1 - currentScroll / checkpoint;
}
document.querySelector(".intro").style.opacity = opacity;
};
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
This is my try. But it does not work.
In short. My theory is to map the difference between the checkpoint variable 2400 and the height variable 3000 to a value between 0.0 and 1. Then assign it to the opacity of the Div. But sadly my head cant figure it out.
useEffect(() => {
const handleScroll = event => {
let opacity;
const height = document.documentElement.scrollHeight - window.innerHeight
const checkpoint = height - 700;
const currentScroll = window.scrollY;
// if (currentScroll >= start) {
if (currentScroll <= checkpoint) {
opacity = 0
console.log('if opacity: ',opacity)
} else {
opacity = currentScroll / checkpoint * 1;
console.log('else opacity: ',opacity)
}
document.querySelector(".footer").style.opacity = opacity;
};
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
Any help here would be greatly appreciated!
-R
Please check this code
import React, { useEffect, useState } from "react";
export default function App() {
const [currentScroll, setCurrentScroll] = useState(0);
window.onscroll = function (e) {
// console.log(window.scrollY);
setCurrentScroll(window.scrollY);
};
useEffect(() => {
console.log(currentScroll);
},
[currentScroll]
);
return (
<div>
<h1>Hello World</h1>
.....
</div>
);
}
GSAP ScrollTrigger example.
ScrollTrigger.create({ trigger: document.body, start: "top top", end: "bottom bottom", // onCallback function });
I have minimal to no experience with HTML/CSS/JS so most of this is copy and pasted. I am using a website building service called cargo. I am trying to change the background color based on the scroll position of the user. Everything works perfectly when starting at the top and scrolling down. But scrolling up does not allow the colors to change at all (except for the "body" color once you reach the top).
HTML/JS:
<script>
function changeBackground(){
if(scrollY >= 300 && scrollY < 900) {
document.body.classList.add('bg-color');
}
else if(scrollY >= 900 && scrollY < 1900){
document.body.classList.add('bg-color-orangeyellow');
}
else if(scrollY >=1900 && scrollY < 2700){
document.body.classList.add('bg-color-white');
}
else{
document.body.classList.remove('bg-color');
document.body.classList.remove('bg-color-orangeyellow');
document.body.classList.remove('bg-color-white');
}
}
addEventListener('scroll', changeBackground);
</script>
CSS:
body {
background-color:rgb(166, 199, 255);
transition: all 0.5s ease;
}
.bg-color{
background-color: #11923d;
}
.bg-color-orangeyellow{
background-color: #ffb217;
}
.bg-color-white{
background-color: white;
The problem is that in each if statement you're adding classes but not removing them.
One option would be to remove the other classes in each if statement, you could also just set the background color with inline style instead to avoid having to toggle these classes on and off like so:
function changeBackground(){
const bodStyle = document.body.style;
if(scrollY >= 300 && scrollY < 900) {
bodStyle.backgroundColor = '#11923d';
}
else if(scrollY >= 900 && scrollY < 1900){
bodStyle.backgroundColor = '#ffb217';
}
else if(scrollY >=1900 && scrollY < 2700){
bodStyle.backgroundColor = '#ffffff'
}
else{
bodStyle.backgroundColor = 'rgb(166, 199, 255)';
}
}
document.addEventListener('scroll', changeBackground);
body {
background-color: rgb(166, 199, 255);
transition: all 0.5s ease;
height: 5000px;
}
Note: I only added the height to the CSS so you could scroll in the code snippet.
Basically your code exists on the first conditional block that is matched and else is not called, so those classes are not removed as you go back up. You could make your code a bit more dynamic like this.
function changeBackground() {
const positions = [{
dist: (scrollY >= 300) && (scrollY < 900),
cls: 'bg-color'
},
{
dist: (scrollY >= 900) && (scrollY < 1900),
cls: 'bg-color-orangeyellow'
},
{
dist: (scrollY >= 1900) && (scrollY < 2700),
cls: 'bg-color-white'
}
]
positions.forEach(({
dist,
cls
}) => {
const action = dist ? 'add' : 'remove'
document.body.classList[action](cls)
})
}
addEventListener('scroll', changeBackground);
body {
background-color: rgb(166, 199, 255);
transition: all 0.5s ease;
height: 2700px;
}
.bg-color {
background-color: #11923d;
}
.bg-color-orangeyellow {
background-color: #ffb217;
}
.bg-color-white {
background-color: white;
}
I'm using this code to make my sticky navbar disappear on scroll down and re-appear on scroll up. However this code is pretty precise resulting sometimes in starting one of both animations without actually scrolling.
What I'm trying to achieve is that a user should scroll 20px down before the if statement runs. Same if they would scroll up again...
https://jsfiddle.net/as1tpbjw/2/
const body = document.querySelector("#navbar");;
let lastScroll = 0;
window.addEventListener("scroll", () => {
const currentScroll = window.pageYOffset;
if (currentScroll <= 0) {
body.classList.remove("scroll-up");
return;
}
if (currentScroll > lastScroll && !body.classList.contains("scroll-down")) {
body.classList.remove("scroll-up");
body.classList.add("scroll-down");
} else if (
currentScroll < lastScroll &&
body.classList.contains("scroll-down")
) {
body.classList.remove("scroll-down");
body.classList.add("scroll-up");
}
lastScroll = currentScroll;
});
As far as I can see, in my relatively old version of Firefox, it works well.
I added if (Math.abs(currentScroll - lastScroll) < 20) { return; } and this adds a 20px delay either way.
Also, that scroll-up class doesn't seem to be doing anything in the fiddle.
Update:
If you want an animation, you can replace the CSS for .scroll-down and add a transition to #navbar:
#navbar.scroll-down {
height: 0;
}
#navbar {
/* … */
transition: height .5s;
}
Not only does scroll-up do nothing, but the following code even breaks (doesn't show the navbar) when you scroll to the top:
if (currentScroll <= 0) {
body.classList.remove("scroll-up");
return;
}
You may want to remove it.
const body = document.querySelector("#navbar");
let lastScroll = 0;
window.addEventListener("scroll", () => {
const currentScroll = window.pageYOffset;
if (Math.abs(currentScroll - lastScroll) < 20) {
return;
}
if (currentScroll > lastScroll) {
body.classList.add("scroll-down");
} else {
body.classList.remove("scroll-down");
}
lastScroll = currentScroll;
});
body {
margin: 0;
min-height: 200vh;
}
#navbar.scroll-down {
height: 0;
}
#navbar {
height: 50px;
background: red;
position: sticky;
top: 0;
left: 0;
transition: height .5s;
}
<body>
<div id="navbar">
</div>
</body>
I am developing this site: https://studioboom.superhi.com/
Is it possible to apply the image click to only the first section, so once scrolled you are able to click on links rather than add an image.
JS:
const images = [
'benjones_flip1.jpg',
'benjones_home1.jpg',
'ben_jones_ts2.jpg',
'benjones_gs1.jpg',
'benjones_jt1.jpg',
'benjones_dlf4.jpg'
]
let i = 0
function placeImage(x, y) {
const nextImage = images[i]
const img = document.createElement('img')
img.classList.add('external-loaded-img')
img.setAttribute('src', nextImage)
img.style.left = x + 'px'
img.style.top = y + 'px'
document.body.appendChild(img)
i = i + 1
if (i >= images.length) {
i = 0
}
}
document.addEventListener('click', function(event) {
event.preventDefault()
placeImage(event.pageX, event.pageY)
})
document.addEventListener('touchend', function(event) {
event.preventDefault()
placeImage(event.pageX, event.pageY)
})
.external-loaded-img {
position: absolute;
transform: translate(-50%, -50%) scale(0.5);
animation: fadein 0.5s;
z-index: 10;
overflow: hidden;
}
#keyframes fadein {
0% {opacity: 0;}
100% {opacity: 1;}
}
Either wait to set up your event handlers until the container of the elements you want them to apply to are present in the page, and then hook up the handlers on that container:
container.addEventListner('click', /*...*/);
container.addEventListner('touchend', /*...*/);
...or keep them hooked up on document, but check when the event occurs that it passed through that container ("event delegation"):
document.addEventListner('click', function(event) {
if (!event.target.closest("selector-for-the-container")) {
return;
}
// ...
});
document.addEventListner('touchend', /*...*/);
if (!event.target.closest("selector-for-the-container")) {
return;
}
// ...
});
More on closest on MDN, including information about polyfills if needed.
document.querySelector(".about").addEventListener('click', function(event) {
event.preventDefault()
placeImage(event.pageX, event.pageY)
})
Something like this does work, if I am clicking on section.photo1, if I clicking on an actual image, it doesn't. Is there a work around for this?
document.addEventListener('click', function(event) {
if (!event.target.closest("section.photo1")) {
return;
}
event.preventDefault()
placeImage(event.pageX, event.pageY)
})
I have a screen div overlay on top of a supersized banner set. From the start the overlay needs to be set to 0.5 opacity, then when the user starts scrolling over a period of about 300px scroll it fade gently to 0.9 opacity then stops at that, if the user scrolls back up to less than 300px from top then it starts to fade slowly back to 0.5 opacity. I'm just using a background color on the div for this.
I'm a little stuck though. I have the below so far but as you start scrolling it goes to 0 opacity then starts from that and fade to 0.9, then at 300px it goes to 1 opacity then after 301px if jumps back to 0.9 opacity.
$(function () {
divFade = $(".fadeScreen");
var toggleHeader = function (noAnimate) {
var threshold = 1,
fadeLength = 300,
opacity,
scrollTop = $(document).scrollTop();
if (scrollTop < threshold) {
opacity = 0.5;
} else if (scrollTop > threshold + fadeLength) {
opacity = 0.9;
} else {
if (noAnimate) {
opacity = 0.9;
} else {
opacity = (scrollTop - threshold) / fadeLength;
}
}
divFade.css("opacity", opacity);
};
toggleHeader(true);
$(window).scroll(function () {toggleHeader();});
});
I just need it so when the page is loaded the opacity is 0.5, between 0-300px scrolling it changes slowly to 0.9 and stays, then when scrolling back up it fades back to 0.5 opacity.
Thanks for any help.
How about this
$(function() {
divFade = $(".fadeScreen");
var toggleHeader = function(noAnimate) {
var threshold = 1,
fadeLength = 300,
minOpacity = 0.5,
maxOpacity = 0.9,
opacity = minOpacity,
opacityDiff = (maxOpacity - minOpacity),
scrollTop = $(document).scrollTop();
if (scrollTop < fadeLength) {
opacity += (scrollTop / fadeLength) * opacityDiff;
} else {
opacity = maxOpacity;
}
console.log(scrollTop);
divFade.css("opacity", opacity);
};
toggleHeader(true);
$(window).scroll(function() {
toggleHeader();
});
});