I am trying to build a Showcase
component, similar to the one seen here , where the user cycles through different content as they scroll:
I'm making the section fixed by using some CSS:
.sticky {
position: sticky;
}
.top-0 {
top: 0;
}
Applied to my HTML:
<section
ref={(r) => this.ref = r}
className={`vh-500 bg-near-white z-max pv6-ns pv3 bg-near-white min-vh-100
...
`}>
<div className='sticky top-0 vh-100'>
Using the ref
on my HTML element, I work out the area where the Showcase
component is sticky by seeing the scrollY
is relation to the top and bottom of the component itself:
componentDidMount() {
if (this.ref) {
this.setState(
{
firstThreshold: this.ref.getBoundingClientRect().top,
secondThreshold: window.innerHeight * amount
},
// tslint:disable-next-line:no-console
() => console.log(this.state, "state")
);
}
window.addEventListener("scroll", this.handleScroll);
}
Then in my handleScroll()
function I detect when we're scrolling through the Showcase
component:
// if we're scrolling through the Showcase component
if (scrollY >= firstThreshold && scrollY <= secondThreshold) {
...
}
Now here's the bit I'm lost with:
I get the height of the Component by multiplying the viewport height with the amount of chapters of a story I want to display in my component:
const chapters = [
{
content: 'Signs up',
title: '',
},
{
content: 'Receives request',
title: '',
},
{
content: 'Gets a shit, rude requests from a person with 0 rating',
title: '',
},
{
content: 'Blocks them',
title: '',
},
{
content: 'Gets a nice request from a person who’s rated 5 stars',
title: '',
},
{
content: 'They agree on terms and accept the request',
title: '',
},
{
content: 'Time elapses',
title: '',
},
{
content: 'Thanks them for the time, gives them 5 stars',
title: '',
},
]
const amount = chapters.length
And in my handleScroll()
function I'm trying to work out which chapter to show as the user scrolls, but I'm not sure how to get there. Here's what I have right now:
for (let i = 0; i < amount; i++) {
// tslint:disable-next-line:no-console
console.log(i, "i");
if (scrollY >= (firstThreshold + sectionThreshold) * i) {
// tslint:disable-next-line:no-console
console.log(sectionThreshold * i, "sectionThreshold * i");
this.setState({ currentChapter: i }, () => {
// tslint:disable-next-line:no-console
console.log(
`scrolling inside section: ${this.state.currentChapter}`
);
});
}
}
What I am trying to achieve:
How do I do this?
So I managed to figure it out, I think I was just overthinking it before. Basically inside of the handleScroll(e)
you get the height of each section:
First, get the height of the chapters by dividing the chapterAmount
by the componentHeight
and push the results into an array:
const chapterHeights = [];
for (let index = 0; index < chapters.length; index++) {
const chapterHeight = componentHeight / chapterAmount;
chapterHeights.push(chapterHeight * index);
}
Then loop through chapterHeights
array and compare it to the scroll position, then set the state of the title
and content
which will be rendered in the view.
for (let index = 0; index < chapterHeights.length; index++) {
// console.log(chapterHeights[index], "chapterHeights[index]");
const chapterLength = chapterHeights[index];
if (scrollY >= chapterLength) {
this.setState({
title: chapters[index].title,
content: chapters[index].content,
})
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.