A simple image slider that uses ReactCSSTransitionGroup for animations.
A Pen by Joseph Martucci on CodePen.
<div id="carousel"></div> |
A simple image slider that uses ReactCSSTransitionGroup for animations.
A Pen by Joseph Martucci on CodePen.
// Change the slide transition type. | |
var transition = 'scale'; | |
// try translate, scale, blur, rotate | |
var appearTransition = true; | |
// Change it to true to add an appear transition that fades the image in from grayscale to full color. | |
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup; | |
var ReactDOM = ReactDOM; | |
var slides = [ | |
'https://images.unsplash.com/photo-1444703686981-a3abbc4d4fe3?fit=crop&fm=jpg&h=825&q=80&w=1325', | |
'https://images.unsplash.com/photo-1445251836269-d158eaa028a6?fit=crop&fm=jpg&h=825&q=80&w=1325', | |
'https://images.unsplash.com/photo-1443926818681-717d074a57af?fit=crop&fm=jpg&h=825&q=80&w=1325' | |
]; | |
class Carousel extends React.Component{ | |
constructor(props){ | |
super(props); | |
this.state = { | |
counter: 0 | |
}; | |
this.prevSlide = this.prevSlide.bind(this); | |
this.nextSlide = this.nextSlide.bind(this); | |
} | |
prevSlide(){ | |
var prevSlide = this.state.counter - 1 < 0 ? this.props.slides.length - 1 : this.state.counter - 1; | |
this.setState({ | |
counter: prevSlide | |
}) | |
} | |
nextSlide(){ | |
var nextSlide = this.state.counter + 1 < this.props.slides.length ? this.state.counter + 1 : 0; | |
this.setState({ | |
counter: nextSlide | |
}) | |
} | |
render(){ | |
var style = { | |
backgroundImage : 'url(' + this.props.slides[this.state.counter] + ')' | |
} | |
return( | |
<div className="carousel"> | |
<div className="carousel__prev" onClick={this.prevSlide}>◀︎</div> | |
<div className="carousel__next" onClick={this.nextSlide}>▶︎</div> | |
<ReactCSSTransitionGroup transitionName={transition} transitionEnterTimeout={500} transitionLeaveTimeout={500} component="div" className="carousel__slide" transitionAppear={appearTransition} transitionAppearTimeout={1000}> | |
<div style={style} key={this.state.counter}></div> | |
</ReactCSSTransitionGroup> | |
</div> | |
) | |
} | |
} | |
ReactDOM.render(<Carousel slides={slides} />, document.getElementById('carousel')); |
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.0/react-with-addons.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.0/react-dom.js"></script> |
body{ | |
overflow: hidden; | |
} | |
.carousel{ | |
width: 100vw; | |
height: 100vh; | |
overflow: hidden; | |
&__prev, &__next{ | |
cursor: pointer; | |
position: absolute; | |
background: rgba(0,0,0,.6); | |
font-size: 32px; | |
color: white; | |
width: 60px; | |
height: 60px; | |
text-align: center; | |
line-height: 60px; | |
top: 50%; | |
margin-top: -30px; | |
z-index: 1000; | |
} | |
&__prev{ | |
left: 40px; | |
} | |
&__next{ | |
right: 40px; | |
} | |
&__slide{ | |
width: 100%; | |
height: 100%; | |
div{ | |
position: absolute; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background-size: cover; | |
} | |
} | |
} | |
.translate-enter { | |
transform: translateX(100vw); | |
} | |
.translate-enter.translate-enter-active { | |
transform: translateX(0); | |
transition: all 500ms ease-in-out; | |
} | |
.translate-leave { | |
transform: translateX(0); | |
} | |
.translate-leave.translate-leave-active { | |
transform: translateX(-100vw); | |
transition: all 500ms ease-in-out; | |
} | |
.scale-appear, .blur-appear, .rotate-appear, .translate-appear{ | |
filter: grayscale(100%); | |
transition: all 1000ms ease-in-out; | |
} | |
.scale-appear.scale-appear-active, .blur-appear.blur-appear-active, .rotate-appear.rotate-appear-active, .translate-appear.translate-appear-active{ | |
filter: grayscale(0); | |
} | |
.scale-enter { | |
transform: scale(1); | |
} | |
.scale-enter.scale-enter-active { | |
transform: scale(1); | |
transition: all 500ms ease-in-out; | |
} | |
.scale-leave { | |
transform: scale(1); | |
opacity: 1; | |
} | |
.scale-leave.scale-leave-active { | |
transform: scale(1.2); | |
opacity: .01; | |
transition: all 500ms ease-in-out; | |
} | |
.blur-enter { | |
transform: scale(1); | |
} | |
.blur-enter.blur-enter-active { | |
transform: scale(1); | |
transition: all 500ms ease-in-out; | |
} | |
.blur-leave { | |
transform: scale(1); | |
opacity: 1; | |
} | |
.blur-leave.blur-leave-active { | |
filter: blur(40px); | |
opacity: .01; | |
transition: all 500ms ease-in-out; | |
} | |
.rotate-enter { | |
filter: hue-rotate(-180deg); | |
opacity: .01; | |
} | |
.rotate-enter.rotate-enter-active { | |
filter: hue-rotate(0deg); | |
opacity: 1; | |
transition: all 500ms ease-in-out; | |
} | |
.rotate-leave { | |
filter: hue-rotate(0deg); | |
opacity: 1; | |
} | |
.rotate-leave.rotate-leave-active { | |
filter: hue-rotate(180deg); | |
opacity: .01; | |
transition: all 500ms ease-in-out; | |
} |