Parallax
1
1
1
A single useEffect() can log DOM userRef()/querySelector() elements.
The ParallaxLayer children components need an useState() dependency, that triggers only after the page is useEffect() mounted, to be logged.
//Remember React.strictmode is active when testing
useEffect(() => {
setParallaxLayerMounted(true);
}, []);
const stratosRefs = useRef([]);
useEffect(()=> {
console.log( stratosRefs )
}, [parallaxLayerMounted])
The navbar has to be outside the <Parallax> container, it will cover part of the first ParallaxPage and won't create additional scrollbars.
//It needs a higher zIndex to be visible
//We modify the intersectionObserver() option object for Parallax elements
let options = {
root: base,
rootMargin: "0px 0px -85% 0px",
threshold: 0,
}
<div>
<div className='position-fixed' style={{ height: "5em", top: 0, zIndex: 5}}>
Navbar
</div>
<Parallax pages={3.2} id='finestra' ref={parallaxRef} style={{ height: "100vh" }}>
...
</Parallax>
</div>

A Parallax component won't respond to a scroll event, only to a wheel.
We useRef([]) <ParallaxLayer/> child elements, check useRef() callback function in React4.
We reduce() loop the useRef([]) intersectionObserver target.id, and we assign them to className DOM element. We cache the object result before the intersect.
//The stratosRef target.id and the className DOM pair on the returned object
//On an empty initialValue Object
let latoCol = useRef([])
const colonne = stratosRefs.current.reduce((acc, strat) => {
const matchingCol =
latoCol.current.find((col) => col.className.includes(strat.id));
if (matchingCol) {
acc[strat.id] = matchingCol;
}
return acc;
}, {});
We use the current boundingClientRect.top of the current intersect <ParallaxLayer/> to edit the useRef().style of its paired column (from the cached reduce() object).
We use an array threshold to simulate the scroll event, and remove the navbar height from the calc().
//For each threshold intersect we edit the current paired column
let coloptions = {
root: finestra.current.container.current,
rootMargin: "0px",
threshold: [...Array(150).keys()].map(x => x / 150),
}
function scrolled(entries){
entries.forEach((entry)=>{
if(entry.isIntersecting && entry.boundingClientRect.top <= 75 ){
reffe = colonne[entry.target.id] //from the cached object
requestAnimationFrame(() => {
reffe.style.height =
`calc(100vh + ${entry.boundingClientRect.top - 75 + "px"} )`;
});
}
})
}
let observer1 = new IntersectionObserver(scrolled, coloptions)
stratosRefs.current.forEach((valo1)=>{
observer1.observe(valo1)
})

1
1
1
We create an absolute <parallaxLayer/> between the pages, that ignores the overflow.
<ParallaxLayer offset={1.37} sticky={{start: 1.37, end: 1.37 }}
style={{height: 0, display: "inline-block"}}>
<>
<div className="d-inline-block">
...
</div>
</>
</ParallaxLayer>
1
1
1
1
We can't relative import files from the public folder, so we create a src folder.
We can overlay <parallaxLayer/> as absolute layers, their display depends on their order. When overlaying svg files we cut the svg extra borders we use https://svgcrop.com/, which will keep the svg aspect ratio with less space.
//Put the background color on the top overlay so it doesn't cover the other elements
//We cannot import SVG files from the public folder, so we need an src folder
import { ReactComponent as Bulb } from "./source/bulb.svg"
<Parallax pages={3.2} id='finestra' ref={parallaxRef} style={{ height: "100vh" }}>
<ParallaxLayer offset={0.1} className='bg-primary'>
<Bulb2 className='position-relative bg-danger'
style={{fill: "orange",height: "45vh",width: "12vw",left: "-15vw",top: "0%"}}/>
</ParallaxLayer>
...
<ParallaxLayer offset={0.1}>
<div id='tunefuse' ref={(ref) => (stratosRefs.current[0] = ref)}>
<h1>First page</h1>
</div>
</ParallaxLayer>
</Parallax>

1
1
1
1
1
Last updated
Was this helpful?