Reputation: 1375
I am creating a carousel and there are 2 buttons Next and Previous. on clicking Next it should slide from left to right and on clicking Previous it should slide from right to left. (I don't want to use any plugin)
My React container:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { prevItem, nextItem, initItem } from '../actions/index';
import { bindActionCreators } from 'redux';
import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup';
class Carousel extends Component{
previous(){
this.props.prevItem();
}
next(){
this.props.nextItem();
}
componentDidMount(){
this.props.initItem();
}
renderItem(){
const {item} = this.props;
const webLink = `http://${item.link}`;
const transitionOptions = {
transitionName: 'slide',
transitionEnterTimeout: 1000,
transitionLeaveTimeout: 1000
};
return(
<CSSTransitionGroup {...transitionOptions}>
<div className="carousel__item" key={item.id}>
<img className="carousel__image" src={item.imageurl}/>
<div className="carousel__text">
<h3>{item.title}</h3>
<p>{item.synopsis}</p>
<a href={webLink} target="_black">{item.link}</a>
</div>
</div>
</CSSTransitionGroup>
)
}
render(){
return(
<div className="carousel">
{this.renderItem()}
<div className="carousel__prev" onClick={this.previous.bind(this)}>
<i className="fa fa-chevron-left"></i>
</div>
<div className="carousel__next" onClick={this.next.bind(this)}>
<i className="fa fa-chevron-right"></i>
</div>
</div>
)
}
}
function mapStateToProps(state){
return {item: state.item};
}
function mapDispatchToProps(dispatch){
return bindActionCreators({
initItem: initItem,
nextItem: nextItem,
prevItem: prevItem
}, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(Carousel);
Any my Style.css is:
.carousel{
width: 100%;
border: 1px solid #ccc;
margin-top: 100px;
position: relative;
}
.carousel__item{
width: 100%;
color: #fff;
position: relative;
}
.carousel__item img{
width: 100%;
background: rgba(0,0,0,.6);
}
.carousel__text{
text-align: center;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.carousel__text a:hover,
.carousel__text a{
color: #fff;
}
.carousel__prev{
position: absolute;
left: 0;
top: 50%;
color: #fff;
margin-left: 10px;
cursor: pointer;
font-size: 25px;
}
.carousel__next{
position: absolute;
right: 0;
top: 50%;
color: #fff;
margin-right: 10px;
cursor: pointer;
font-size: 25px;
}
.slide-enter{
transform: translate(100%);
}
.slide-enter-active{
transform: translate(0%);
transition: transform 1000ms ease-in-out;
}
.slide-leave{
transform: translate(0%);
}
.slide-leave-active{
transform: translate(-100%);
transition: transform 1000ms ease-in-out;
}
Apart from the direction, the current slide animation is not correct. when it slides the previous slide is showing below. So basically 2 slides are showing on screen on transition. Do you know how to fix this problem and also address the direction of slide?
Upvotes: 2
Views: 7802
Reputation: 20098
We can create slide animation in the following way using slide for Dialog
const Transition = React.forwardRef(function Transition(props, ref) {
return <Slide direction='up' ref={ref} {...props} />
})
<Dialog
open={open}
TransitionComponent={Transition} // Transition fade
keepMounted
onClose={handleClose}
aria-labelledby='alert-dialog-slide-title'
aria-describedby='alert-dialog-slide-description'
fullWidth
></Dialog>
Upvotes: 0
Reputation: 2356
I just worked through this problem.
In order to slide in the correct direction, you'll need to maintain some state and apply this state to your items via className. Something like this:
render () {
<CSSTransitionGroup
component={MenuWrapper}
transitionName="slide"
transitionEnterTimeout={500}
transitionLeaveTimeout={500}>
{this._renderMenu(this.props.selectedSubMenus[menuIdx], menuIdx)}
</CSSTransitionGroup>
}
_renderMenu = (menu, idx) => {
return (
<Menu key={idx} className={this.state.animationDirection} order={idx}>
content
</Menu>
)
}
Your css should look something like this (note that I'm using styled-components for a few elements):
const menuWidth = "256px";
const MenuWrapper = styled.div`
display: flex;
overflow: hidden;
max-width: ${menuWidth};
`
const Menu = styled.div`
min-width: ${menuWidth};
order: ${props => props.order};
`
.slide-enter.left {
transform: translate(-100%);
}
.slide-enter.slide-enter-active.left {
transform: translate(0%);
transition: transform 500ms ease-in-out;
}
.slide-leave.left {
transform: translate(-100%);
}
.slide-leave.slide-leave-active.left {
transform: translate(0%);
transition: transform 500ms ease-in-out;
}
.slide-enter.right {
transform: translate(0%);
}
.slide-enter.slide-enter-active.right {
transform: translate(-100%);
transition: transform 500ms ease-in-out;
}
.slide-leave.right {
transform: translate(0%);
}
.slide-leave.slide-leave-active.right {
transform: translate(-100%);
transition: transform 500ms ease-in-out;
}
Note that I used flexbox in order to fix the display problem (as well as some hard-coded widths)
Hope this helps
Upvotes: 2