Skip to content

Instantly share code, notes, and snippets.

@guilhermemarconi
Last active September 2, 2020 21:33
Show Gist options
  • Save guilhermemarconi/a923e85811b8b43127e471f15c47eca5 to your computer and use it in GitHub Desktop.
Save guilhermemarconi/a923e85811b8b43127e471f15c47eca5 to your computer and use it in GitHub Desktop.
Bullets Tracking
import React, { useState } from 'react';
import Section from './Section';
import Bullets from './Bullets';
const images = ['01', '02', '03', '04', '05'];
function App() {
const [activeSection, setActiveSection] = useState(0);
return (
<>
<header>FARM</header>
<main>
{images.map((image, index) => <Section src={image} index={index} key={index} activeSection={activeSection} setActiveSection={setActiveSection} length={images.length} />)}
<Bullets length={images.length} active={activeSection} />
</main>
<footer>Footer</footer>
</>
);
}
export default App;
import React from 'react'
function Bullets({ length, active = 0 }) {
if (!length) return null;
return (
<ul className="nav-bullets">
{[...new Array(length)].map((_, index) => (
<li className={active === index ? 'is-active' : ''} key={index} />
))}
</ul>
)
}
export default Bullets;
.nav-bullets {
position: fixed;
top: 50%;
right: 20px;
margin: 0;
padding: 0;
transform: translateY(-50%);
}
.nav-bullets li {
position: relative;
display: block;
width: 10px;
height: 10px;
margin: 10px 0;
border-radius: 50%;
background: white;
}
.nav-bullets li.is-active::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 16px;
height: 16px;
border: 1px solid white;
border-radius: 50%;
background: transparent;
transform: translate(-50%, -50%);
}
.nav-bullets li:first-child { margin-top: 0; }
.nav-bullets li:last-child { margin-bottom: 0; }
.nav-bullets li:only-child { margin: 0; }
import React, { useRef, useState, useEffect } from 'react';
function Section({ src, index, length, activeSection, setActiveSection }) {
const [loaded, setLoaded] = useState(false);
const ref = useRef(null);
function handleScrollPosition() {
try {
const rect = ref.current.getBoundingClientRect();
if (rect.y === 0) {
if (activeSection !== index) {
if (activeSection > index) return;
setActiveSection(index);
} else {
setActiveSection(index);
}
} else if (rect.y < 0) {
setActiveSection(length - 1);
}
} catch (error) {
console.error(error);
}
}
useEffect(() => {
// eslint-disable-next-line no-undef
$(window).on('scroll resize', handleScrollPosition);
setLoaded(true);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<div className="image-wrapper" ref={ref}>
<img src={`/${src}.jpg`} alt="" />
</div>
)
}
export default Section;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment