Essentially, one method to achieve this is by utilizing the concept presented in the comment but modified and tailored for react. The key lies in integrating React Router with the carousel component.
For the routing aspect, you would implement something similar to:
<Route path="/:page"
render={
props => <Layout selectedPage={props.location.state.selectedPage}/>
}
/>
Next, set up the navigation links as follows:
<nav>
<ul className="navigation">
<li>
<Link to={{pathname: '/mypage', state: {selectedPage: 0}}}>
My page
</Link>
</li>
// additional links omitted for brevity
</ul>
</nav>
Below is the main layout component code snippet:
const Layout = props => {
const [radius, setRadius] = useState(0);
const [theta, setTheta] = useState(0);
useEffect(() => {
const carousel = document.querySelector('.carousel');
const cells = carousel.querySelectorAll('.carousel__cell');
const cellWidth = carousel.offsetWidth;
const cellCount = cells.length;
setTheta(360/cellCount);
setRadius(Math.round((cellWidth / 2) / Math.tan(Math.PI / cellCount)));
carousel.style.transform = 'translateZ(' + -radius + 'px)';
for (let i = 0; i < cellCount; i++) {
const cell = cells[i];
cell.style.opacity = 1;
const cellAngle = theta * i;
cell.style.transform = 'rotateY(' + cellAngle + 'deg) translateZ(' + radius + 'px)';
}
}, [radius, theta]
);
useEffect(() => props.selectedPage !== undefined && rotateTo(props.selectedPage), [props.selectedPage]);
const rotateTo = n => {
const carousel = document.querySelector('.carousel');
const angle = theta * n * -1;
carousel.style.transform = 'translateZ(' + -radius + 'px) rotateY(' + angle + 'deg)';
};
return (
<div className="scene">
<div className="carousel">
<div className="carousel__cell">1</div>
<div className="carousel__cell">2</div>
<div className="carousel__cell">3</div>
<div className="carousel__cell">4</div>
<div className="carousel__cell">5</div>
<div className="carousel__cell">6</div>
</div>
</div>
);
};
To style it properly, use the following CSS:
.scene {
border: 1px solid #CCC;
position: relative;
width: 100%;
height: calc(100vh - 3em);
margin: 0 auto;
perspective: 1000px;
}
.carousel {
width: 100%;
height: 100%;
position: absolute;
transform: translateZ(-288px);
transform-style: preserve-3d;
transition: transform 1s;
}
.carousel__cell {
position: absolute;
width: calc(100% - 20px);
height: calc(100% - 20px);
left: 10px;
top: 10px;
border: 2px solid black;
line-height: 116px;
font-size: 80px;
font-weight: bold;
color: white;
text-align: center;
transition: transform 1s, opacity 1s;
}
This implementation simplifies the original example provided in the link, excluding vertical rotation and dynamic cell adding functionalities, while ensuring compatibility with react-router. It may not be perfect, but it gets the job done.
For a complete demonstration, visit https://github.com/luinnarn/carousel-demo.