Created
March 2, 2020 14:32
-
-
Save DZuz14/17ad1aa963f01b48782ae31761f84f30 to your computer and use it in GitHub Desktop.
Slider after Smooth Transition
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() | |
useEffect(() => { | |
autoPlayRef.current = nextSlide | |
transitionRef.current = smoothTransition | |
}) | |
useEffect(() => { | |
const play = () => { | |
autoPlayRef.current() | |
} | |
const smooth = () => { | |
transitionRef.current() | |
} | |
const interval = setInterval(play, props.autoPlay * 1000) | |
const transitionEnd = window.addEventListener('transitionend', smooth) | |
return () => { | |
clearInterval(interval) | |
window.removeEventListener('transitionend', transitionEnd) | |
window.removeEventListener('resize', onResize) | |
} | |
}, []) | |
useEffect(() => { | |
if (transition === 0) setState({ ...state, transition: 0.45 }) | |
}, [transition]) | |
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