4

I'm trying to build a custom carousel with React and the react-transition-group package. The core functionality is working, but I'm struggling to write CSS to perform a simultaneous left slide-out of old item and left slide-in of new item. Any suggestions would be greatly appreciated! I've included my failed attempt below.

HTML

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { showModal } from '../actions';
import { CSSTransition, TransitionGroup } from 'react-transition-group'

class FeatureCarousel extends Component {
  constructor(props) {
    super(props);
    this.state = { activeIndex: 0 };
    ...
  }

  ...

  componentDidMount() {
    this.progressSlideshow();
  }

  progressSlideshow() {
    this.timeout = setTimeout(function () {
      this.next();
      this.progressSlideshow();
    }.bind(this), 3000);
  }

  ...

  render() {
    const { activeIndex } = this.state;
    const { articles, level } = this.props;

    const slides = articles.map((article, index) => {
      let { urlToImage, title } = article;

      return (
        <CSSTransition
          key={index}
          classNames="slide"
          timeout={{ enter: 500, exit: 500 }}>
          <div
            key={index}
            className="carousel-item"
            onMouseEnter={this.handleMouseEnter}
            onMouseLeave={this.handleMouseLeave} >
            <div className="image-wrapper">
              <img src={urlToImage} alt={title} />
            </div>
            <div className="carousel-caption d-md-block">
              <h4>{title}</h4>
            </div>
          </div>
        </CSSTransition>
      )
    })

    return (
        <div className="carousel slide" data-ride="carousel">
          <div className="carousel-inner">
            <TransitionGroup>
              {slides[activeIndex]}
            </TransitionGroup>
          </div>
          <a className="carousel-control-prev" role="button" onClick={e => this.previouse()}>
            <span className="carousel-control-prev-icon" aria-hidden="true" />
            <span className="sr-only">Previous</span>
          </a>
          <a className="carousel-control-next" role="button" onClick={() => this.next()}>
            <span className="carousel-control-next-icon" aria-hidden="true" />
            <span className="sr-only">Next</span>
          </a>
        </div>
    );
  }
}

export default connect(null, { showModal })(FeatureCarousel);

CSS

.slide-enter {
    transform: translate(-100%);
}
.slide-enter.slide-enter-active {
    transform: translate(0%);
    transition: transform 500ms ease-in-out;
}
.slide-leave {
    transform: translate(-100%);
}
.slide-leave.slide-leave-active {
    transform: translate(0%);
    transition: transform 500ms ease-in-out;
}
lgants
  • 3,665
  • 3
  • 22
  • 33
  • I have a similar problem. I'm trying to create a carousel. My classes are attached correctly to the html for the "arrive" part of the animation but then after a given slide is shown the enter and exit classes disappear. – Raydot Oct 18 '18 at 19:22

1 Answers1

2

I have the same problem with my custom gallery, below I paste my styles for that.
move-next: show the next slide from the right side
move-prev: show the next slide from the left side

The main idea is using position:absolute for invisible slide

 .move-next {
    .slide-enter {
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        transform: translate(100%, 0);
        opacity: 0;
    }

    .slide-enter-active {
        transform: translate(0, 0);
        transition: all $animateInterval ease;
        opacity: 1;
    }

    .slide-exit{
        transform: translate(0, 0);
        opacity: 1;
    }

    .slide-exit-active{
        transition: all $animateInterval ease;
        transform: translate(-100%, 0);
        opacity: 0;
    }
}

.move-prev {
    .slide-enter{
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        opacity: 0;
        transform: translate(-100%, 0);
    }

    .slide-enter-active{
        transition: all $animateInterval ease;
        opacity: 1;
        transform: translate(0, 0);
    }

    .slide-exit{
        opacity: 1;
        transform: translate(0, 0);
    }

    .slide-exit-active{
        transition: all $animateInterval ease;
        opacity: 0;
        transform: translate(100%, 0);
    }
}
Slawa Eremin
  • 5,264
  • 18
  • 28