joshwcomeau / react-flip-move

Effortless animation between DOM changes (eg. list reordering) using the FLIP technique.
http://joshwcomeau.github.io/react-flip-move/examples
MIT License
4.09k stars 256 forks source link

Dynamic animations depending on user action #132

Closed martinklepsch closed 7 years ago

martinklepsch commented 7 years ago

Hey :)

I was wondering if there is a way to animate stuff in a carousel like manner, i.e. slide to left of I click "next" and slide to right if I click "previous" (here's an example).

I see that this isn't quite the list example used in the demos but just wanted to check if I'm missing something or this is just not in the scope of react-flip-move (which otherwise is excellent 👍)

Thanks!

joshwcomeau commented 7 years ago

Hey @martinklepsch!

Interesting question!

The smart advice is to use a solution that targets this problem. I haven't used it personally, but Nuka Carousel looks pretty good. Ken Wheeler's a BAMF, so I'd trust that it works pretty well.

Flip Move theoretically should be able to handle this use-case, you'd just have to build out a lot of the functionality that's given to you "for free" by carousel modules.

For fun, though, I thought a bit about what you'd need to do if you wanted to use FlipMove. You could use CSS to hide all but a single item outside of the container (or viewport, if it's full screen):

    v Item 1    
   ___   ________   ___
  |   | |        | |   |  < Item 3
  |___| |        | |___|
        |________|
            ^ viewport

Essentially with overflow: hidden you can hide the previous/next items in the carousel. As the list shuffles, items would slide into view. To shuffle the items, you'd just need to "rotate" the array. So if your photos are [1, 2, 3, 4, 5], and the user clicks "next", you'd want to re-render with the array as [2, 3, 4, 5, 1].

Something like:

// Create a 'rotate' function that will handle previous/next
const rotate = (arr, direction = 'forwards') => {
  switch (direction) {
    case 'forwards': {
      const [head, ...tail] = arr;

      return [...tail, head]
    }

    case 'backwards':
      // omitted for brevity
  }
}
class Carousel extends Component {
  nextPhoto() {
    this.setState({ photos: rotate(this.state.photos, 'forwards') });
  }
}

Again, though, you're probably better off going with a project built to handle carousels. My solution doesn't offer browser history tie-in, doesn't provide those little dots so that you can tell where you are in the list, doesn't handle fading in/out items as they move, etc.

joshwcomeau commented 7 years ago

Closing this, since it's not a bug report, nor something I'm likely to tackle (I don't really like carousels).

Let me know how it goes if you do decide to use FlipMove though!

martinklepsch commented 7 years ago

@joshwcomeau thanks for the pointers Josh! My ultimate goal isn't actually to build a carousel but rather be able to dynamically determine what specific animation to use for a given enter/leave animation. Cheers!