I am building a carousel component in react -- and the client wants there to be an autoscroll option - my concern though is interfering with the user interface -- what kind of logic to build to break/pause the autoscroll without interfering with the user trying to use it in the first place. So hover detection is needed?
//Original Carousel https://codesandbox.io/s/holy-https-h0yv3
//With current autoscroll option on - but ignoring all UI considerations https://codesandbox.io/s/nervous-brown-2inki?file=/src/Carousel/Carousel.js
also - the carousel after going through the slides - will just ZIP through the deck - without being able to snap to the slide - so that's another issue
import React, { Component } from 'react';
import Button from '@material-ui/core/Button';
import ChevronLeftIcon from '@material-ui/icons/ChevronLeft';
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
import './Carousel.scss';
class Carousel extends Component {
constructor() {
super();
this.myRef = React.createRef();
this.state = {
currentSlide: 0,
slideWidth: 0,
slideCount: 0
};
this.updateDimensions = this.updateDimensions.bind(this);
this.handleKeyPress = this.handleKeyPress.bind(this);
this.prev = this.prev.bind(this);
this.next = this.next.bind(this);
}
componentDidMount() {
window.addEventListener("resize", this.updateDimensions);
this.updateDimensions();
this.setState({
slideCount: this.props.items.length
});
this.autoSlide();
}
componentWillUnmount() {
window.removeEventListener("resize", this.updateDimensions);
}
handleKeyPress(e) {
if (e.keyCode === 39) {
this.next();
}
if (e.keyCode === 37) {
this.prev();
}
}
updateDimensions(){
//update the dimensions of the slide for responsiveness
this.setState({
slideWidth: this.myRef.current.getBoundingClientRect().width
});
}
prev(){
//if the current slide won't hit negative slide - change current slide
if(this.state.currentSlide > 0){
let prevSlide = this.state.currentSlide-1;
this.setState({
currentSlide: prevSlide
});
}
}
next(){
//if the next slide will not go beyond the items - change current slide
if(this.state.currentSlide < this.props.items.length-1){
let nextSlide = this.state.currentSlide+1;
this.setState({
currentSlide: nextSlide
});
}
}
selected(slide){
console.log(slide)
this.setState({
currentSlide: slide
});
}
autoSlide(){
let that = this;
let count = this.props.items.length;
let i = 0;
setInterval(function(){
that.selected(i);
i++;
if(count === i){
i=0;//resets
}
}, 3000);
}
render() {
return (
<div ref={this.myRef} className="carousel" onKeyDown={this.handleKeyPress} tabIndex={-1}>
<div className="carousel-holder">
<div className="carousel-wrapper">
<div
className="slide-wrapper"
style={{
left: -this.state.slideWidth*this.state.currentSlide,
width: this.state.slideWidth*this.state.slideCount
}}
>
{
this.props.items.map((item, j) => {
return(
<div
key={j}
className="slide"
style={{
width: this.state.slideWidth
}}
>
<div className={"gutter " + (this.props.hasGutter? "has-gutter" : "")}>
{item.slide}
</div>
</div>
)
})
}
</div>
</div>
<Button
className="carousel-arrow prev-arrow"
onClick={this.prev}
disabled={(this.state.currentSlide === 0)}
>
<ChevronLeftIcon />
</Button>
<Button
className="carousel-arrow next-arrow"
onClick={this.next}
disabled={(this.state.currentSlide === this.props.items.length-1)}
>
<ChevronRightIcon />
</Button>
</div>
<div className="carousel-dots">
<ul className="dot-wrapper">
{
this.props.items.map((item, x) => {
return (
<li
key={x}
className={(this.state.currentSlide === x? "selected" : "")}
>
<Button
className="dot"
onClick={() => this.selected(x)}
/>
</li>
)
})
}
</ul>
</div>
</div>
);
}
}
export default Carousel;
