Created
February 27, 2019 09:00
-
-
Save johndavedecano/334b794fb2997f8eaedd9f2a05f08c4f to your computer and use it in GitHub Desktop.
Slider
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from 'react'; | |
import { render } from 'react-dom'; | |
import Slider from './Slider' | |
import SliderItem from './SliderItem' | |
import './style.css'; | |
class App extends Component { | |
constructor() { | |
super(); | |
this.state = { | |
name: 'React' | |
}; | |
} | |
handleChangeSlide = index => { | |
console.log(index) | |
} | |
render() { | |
return ( | |
<div className="Slider__Wrapper"> | |
<Slider onChangeSlide={this.handleChangeSlide}> | |
<SliderItem> | |
<img src="https://placeimg.com/1000/500/animals" /> | |
</SliderItem> | |
<SliderItem> | |
<img src="https://placeimg.com/1000/500/arch" /> | |
</SliderItem> | |
<SliderItem> | |
<img src="https://placeimg.com/1000/500/nature" /> | |
</SliderItem> | |
<SliderItem> | |
<img src="https://placeimg.com/1000/500/people" /> | |
</SliderItem> | |
</Slider> | |
</div> | |
); | |
} | |
} | |
render(<App />, document.getElementById('root')); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react' | |
import debounce from 'lodash/debounce' | |
import PT from 'prop-types' | |
class Slider extends React.Component { | |
static defaultProps = { | |
timeout: 3000, | |
autoPlay: true, | |
transition: 'ease', | |
transitionDelay: '.5s', | |
onChangeSlide: () => { }, | |
} | |
static propTypes = { | |
timeout: PT.number, | |
autoPlay: PT.bool, | |
transition: PT.oneOf([ | |
'ease', | |
'linear', | |
'ease-in', | |
'ease-out', | |
'ease-in-out' | |
]), | |
transitionDelay: PT.string, | |
onChangeSlide: PT.func, | |
} | |
state = { | |
currentIndex: 0, | |
width: 0, | |
isResizing: false | |
} | |
sliderRef = React.createRef() | |
contentRef = React.createRef() | |
tick = null | |
resizeTick = null | |
resizeTimeout = 500 | |
constructor(props) { | |
super(props) | |
this.handleWindowResize = debounce(this.handleWindowResize) | |
} | |
componentDidMount() { | |
this.calculateContentWidth() | |
this.calculateSliderWidth() | |
window.addEventListener("resize", this.handleWindowResize) | |
this.setupTransition() | |
} | |
componentWillUnmount() { | |
window.removeEventListener("resize", this.handleWindowResize) | |
this.clearTimers() | |
} | |
getParentWidth() { | |
return this.sliderRef.current.parentElement.clientWidth | |
} | |
calculateSliderWidth() { | |
const width = this.getParentWidth() | |
this.sliderRef.current.style.maxWidth = `${width}px` | |
this.sliderRef.current.querySelectorAll('.Slider__Item').forEach(el => { | |
el.style.width = `${width}px !important` | |
}) | |
} | |
calculateContentWidth() { | |
const width = this.sliderRef.current.offsetWidth * this.props.children.length | |
this.contentRef.current.style.width = `${width}px` | |
} | |
handleWindowResize = () => { | |
this.clearTimers() | |
this.resizeTick = setTimeout(this.doneResizing, this.resizeTimeout) | |
} | |
doneResizing = () => { | |
this.clearTimers() | |
this.calculateContentWidth() | |
this.calculateSliderWidth() | |
this.setupTransition() | |
} | |
setupTransition = () => { | |
if (this.props.autoPlay) { | |
this.tick = setInterval(this.handleTransition, this.props.timeout) | |
} | |
} | |
clearTimers = () => { | |
clearTimeout(this.resizeTimeout) | |
clearInterval(this.tick) | |
} | |
slideToIndex = (currentIndex) => { | |
const { transitionDelay, transition, onChangeSlide } = this.props | |
onChangeSlide({ | |
prevIndex: this.state.currentIndex, | |
newIndex: currentIndex, | |
}) | |
this.setState({ | |
currentIndex, | |
}, () => { | |
if (currentIndex === 0) { | |
this.contentRef.current.style.transition = `.10s ${this.props.transition}` | |
this.contentRef.current.style.transform = 'translate(0%)' | |
} else { | |
const parentWidth = this.getParentWidth() | |
const fullWidth = parentWidth * this.props.children.length | |
const indexWidth = parentWidth * currentIndex | |
const percentageValue = indexWidth / fullWidth * 100 | |
this.contentRef.current.style.transform = `translate(-${percentageValue}%)` | |
this.contentRef.current.style.transition = `${transitionDelay} ${transition}` | |
} | |
}) | |
} | |
handleTransition = () => { | |
this.slideToIndex(this.getIndexSlideIndex()) | |
} | |
getIndexSlideIndex = () => { | |
const lastIndex = this.props.children.length - 1 | |
if (this.state.currentIndex === lastIndex) { | |
return 0 | |
} else { | |
return this.state.currentIndex + 1 | |
} | |
} | |
render() { | |
const { children } = this.props | |
return ( | |
<div ref={this.sliderRef} className="Slider"> | |
<div ref={this.contentRef} className="Slider__Content"> | |
{children} | |
</div> | |
</div> | |
) | |
} | |
} | |
export default Slider |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react' | |
import PT from 'prop-types' | |
class SliderItem extends React.Component { | |
static defaultProps = { | |
width: '' | |
} | |
static propTypes = { | |
width: PT.string, | |
} | |
render() { | |
const { children, width } = this.props | |
return ( | |
<div style={{ width }} className="Slider__Item"> | |
{children} | |
</div> | |
) | |
} | |
} | |
export default SliderItem |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
html, body, * { | |
margin: 0; | |
padding: 0; | |
} | |
.Slider__Wrapper img { | |
width: 100%; | |
max-width: 100%; | |
height: auto; | |
} | |
.Slider { | |
overflow: hidden; | |
scroll-behavior: smooth; | |
} | |
.Slider__Content { | |
transform: translateX(0%); | |
overflow: hidden; | |
display: flex; | |
} | |
.Slider__Item { | |
word-wrap: break-word; | |
overflow: hidden; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment