I use react with Material-UI for my website and I would like to add some transitions. I've used a button so far to make a component appear, but I want it to appear when I scroll to the component then the transition trigger. I am using <Grow/> component from Material-UI, can you help me with that?
Add a comment
|
1 Answer
You can listen to the scroll event in the container element and detect whether the elements inside it is in the viewport like below:
function Scroller({ className, children, trackIds, onScrollToElement }) {
return (
<div
className={className}
onScroll={(e) => {
for (let i = 0; i <= trackIds.length - 1; i++) {
const id = trackIds[i];
const trackedEl = document.getElementById(id);
const scrollerEl = e.currentTarget;
if (
scrollerEl.scrollTop >
trackedEl.offsetTop + trackedEl.offsetHeight - scrollerEl.offsetHeight
) {
onScrollToElement(trackedEl);
}
}
}}
>
{children}
</div>
);
}
Explanation
scrollerElis the scrollable container element. Make sure to set theoverflowCSS property of this element toautoto show the scrollbar when there is not enough space.trackedElis the child element inside the scrollable container to keep track of, when the user scrolls to thetrackedEl, the callbackonScrollToElementis invoked.scrollerEl.scrollTop: number of pixels scrolled vertically. This is the scroll 'progress'. Before you scroll, the value is0, as you are scrolling down the value is increase by the pixels you've scrolled.trackedEl.offsetTop + trackedEl.offsetHeight - scrollerEl.offsetHeight: The number of pixels you have to scroll down to see thetrackedEltrackedEl.offsetTop: The distance in pixel of thescrollerEltop position to thetrackedEltop position.trackedEl.offsetHeight: The height oftrackedElincluding padding and border. This means you have to fully see thetrackedElbeforeonScrollToElementfiresscrollerEl.offsetHeight: The height ofscrollerEl. Subtracting this because before you start scrolling, you've already seen the top part of the container.
Usage
const classes = useStyles();
const [showButton, setShowButton] = useState(false);
return (
<Scroller
className={classes.container}
trackIds={["myButton"]}
onScrollToElement={(el) => {
if (el.id === "myButton" && !showButton) {
setShowButton(true);
}
}}
>
<div className={classes.topContent}>
<Typography variant="h4">Top content</Typography>
</div>
<div className={classes.buttonContent}>
<Grow in={showButton}>
<Button id="myButton" variant="contained" color="primary">
Primary
</Button>
</Grow>
</div>
</Scroller>
);
Props:
trackIds: List of ids of the elements to keep track of in theScroller. If we track every elements insideScroller, it will affect the performance in complex UI.onScrollToElement: A callback that is executed when a tracked element is scrolled into view.
Live Demo
9 Comments
Vali Talpas
Sorry but it doesn't work. onScrollToElement return always false and i don't know why
NearHuscarl
Do you mean
onScrollToElement is never called? Did you pass the trackIds list and adding an id to the button? @ValiTalpasVali Talpas
Yes. Should I use
<Scroller /> in app.js? ` `NearHuscarl
Did you set
Scroller overflow style to auto like in my example? @ValiTalpasVali Talpas
Yes, I don't know what I'm doing wrong :(
|