Created
March 2, 2020 15:02
-
-
Save DZuz14/58115c14fedd3e18a801b5baab7ed4da to your computer and use it in GitHub Desktop.
Slider Final!
This file contains hidden or 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
/** @jsx jsx */ | |
import React, { useState, useEffect, useRef } from 'react' | |
import { css, jsx } from '@emotion/core' | |
import SliderContent from './SliderContent' | |
import Slide from './Slide' | |
import Arrow from './Arrow' | |
import Dots from './Dots' | |
const getWidth = () => window.innerWidth | |
/** | |
* @function Slider | |
*/ | |
const Slider = props => { | |
const { slides } = props | |
const firstSlide = slides[0] | |
const secondSlide = slides[1] | |
const lastSlide = slides[slides.length - 1] | |
const [state, setState] = useState({ | |
activeSlide: 0, | |
translate: getWidth(), | |
transition: 0.45, | |
_slides: [lastSlide, firstSlide, secondSlide] | |
}) | |
const { activeSlide, translate, _slides, transition } = state | |
const autoPlayRef = useRef() | |
const transitionRef = useRef() | |
const resizeRef = useRef() | |
useEffect(() => { | |
autoPlayRef.current = nextSlide | |
transitionRef.current = smoothTransition | |
resizeRef.current = handleResize | |
}) | |
useEffect(() => { | |
const play = () => { | |
autoPlayRef.current() | |
} | |
const smooth = e => { | |
if (e.target.className.includes('SliderContent')) { | |
transitionRef.current() | |
} | |
} | |
const resize = () => { | |
resizeRef.current() | |
} | |
const interval = setInterval(play, props.autoPlay * 1000) | |
const transitionEnd = window.addEventListener('transitionend', smooth) | |
const onResize = window.addEventListener('resize', resize) | |
return () => { | |
clearInterval(interval) | |
window.removeEventListener('transitionend', transitionEnd) | |
window.removeEventListener('resize', onResize) | |
} | |
}, []) | |
useEffect(() => { | |
if (transition === 0) setState({ ...state, transition: 0.45 }) | |
}, [transition]) | |
const handleResize = () => { | |
setState({ ...state, translate: getWidth(), transition: 0 }) | |
} | |
const smoothTransition = () => { | |
let _slides = [] | |
// We're at the last slide. | |
if (activeSlide === slides.length - 1) | |
_slides = [slides[slides.length - 2], lastSlide, firstSlide] | |
// We're back at the first slide. Just reset to how it was on initial render | |
else if (activeSlide === 0) _slides = [lastSlide, firstSlide, secondSlide] | |
// Create an array of the previous last slide, and the next two slides that follow it. | |
else _slides = slides.slice(activeSlide - 1, activeSlide + 2) | |
setState({ | |
...state, | |
_slides, | |
transition: 0, | |
translate: getWidth() | |
}) | |
} | |
const nextSlide = () => | |
setState({ | |
...state, | |
translate: translate + getWidth(), | |
activeSlide: activeSlide === slides.length - 1 ? 0 : activeSlide + 1 | |
}) | |
const prevSlide = () => | |
setState({ | |
...state, | |
translate: 0, | |
activeSlide: activeSlide === 0 ? slides.length - 1 : activeSlide - 1 | |
}) | |
return ( | |
<div css={SliderCSS}> | |
<SliderContent | |
translate={translate} | |
transition={transition} | |
width={getWidth() * _slides.length} | |
> | |
{_slides.map((_slide, i) => ( | |
<Slide width={getWidth()} key={_slide + i} content={_slide} /> | |
))} | |
</SliderContent> | |
<Arrow direction="left" handleClick={prevSlide} /> | |
<Arrow direction="right" handleClick={nextSlide} /> | |
<Dots slides={slides} activeSlide={activeSlide} /> | |
</div> | |
) | |
} | |
const SliderCSS = css` | |
position: relative; | |
height: 100vh; | |
width: 100vw; | |
margin: 0 auto; | |
overflow: hidden; | |
white-space: nowrap; | |
` | |
export default Slider |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment