react-native-snap-carousel icon indicating copy to clipboard operation
react-native-snap-carousel copied to clipboard

3D Cube Animation

Open zek opened this issue 5 years ago • 10 comments

Is this a bug report, a feature request, or a question?

Question

Hello everyone,

image

I was using https://github.com/zehfernandes/react-native-3dcube-navigation library to make instagram's story like cube animation but this library doesn't use FlatList so it has performance issues and also it has some bugs. I thought maybe I can use snap-carousel to implement 3dcube navigation since it looks same as in custom interpolations page.

But when I tried to implement this custom animation. I notice _scrollInterpolator converts -1, 0, 1 to -width, 0, width. So I using "pageX - width" as given below is incorrect. I tried to change them to -1, 0, 1 but I get really weird result.

image

I am new to react native animations. Any help would be appreciated.

  _getTransformsFor = i => {
    let scrollX = this._animatedValue.x;
    let pageX = -width * i;

    let translateX = scrollX.interpolate({
      inputRange: [pageX - width, pageX, pageX + width],
      outputRange: [(-width - 1) / TR_POSITION, 0, (width + 1) / TR_POSITION],
      extrapolate: 'clamp'
    });

    let rotateY = scrollX.interpolate({
      inputRange: [pageX - width, pageX, pageX + width],
      outputRange: ['-60deg', '0deg', '60deg'],
      extrapolate: 'clamp'
    });

    let translateXAfterRotate = scrollX.interpolate({
      inputRange: [pageX - width, pageX, pageX + width],
      inputRange: [
        pageX - width,
        pageX - width + 0.1,
        pageX,
        pageX + width - 0.1,
        pageX + width
      ],
      outputRange: [
        -width - 1,
        (-width - 1) / PESPECTIVE,
        0,
        (width + 1) / PESPECTIVE,
        +width + 1
      ],
      extrapolate: 'clamp'
    });

    let opacity = scrollX.interpolate({
      inputRange: [
        pageX - width,
        pageX - width + 10,
        pageX,
        pageX + width - 250,
        pageX + width
      ],
      outputRange: [0, 0.6, 1, 0.6, 0],
      extrapolate: 'clamp'
    });

    return {
      transform: [
        { perspective: width },
        { translateX },
        { rotateY: rotateY },
        { translateX: translateXAfterRotate }
      ],
      opacity: opacity
    };
  };

zek avatar May 09 '19 18:05 zek

What I tried so far


import React, { PureComponent } from 'react';
import Carousel, { getInputRangeFromIndexes } from 'react-native-snap-carousel';
import { Dimensions, Platform, StyleSheet, View } from 'react-native';

const Window = Dimensions.get('window');

const width = Window.width;
const height = Window.height;

const PESPECTIVE = Platform.OS === 'ios' ? 2.38 : 1.7;
const TR_POSITION = Platform.OS === 'ios' ? 2 : 1.5;

const data = [
  { id: 1, color: 'red' },
  { id: 2, color: 'blue' },
  { id: 3, color: 'yellow' },
  { id: 4, color: 'green' },
  { id: 5, color: 'black' },
];

export default class MyCustomCarousel extends PureComponent {

  _scrollInterpolator(index, carouselProps) {
    const range = [1, 0, -1];
    const inputRange = getInputRangeFromIndexes(range, index, carouselProps);
    const outputRange = range;

    return { inputRange, outputRange };
  }

  _animatedStyles(i, scrollX, carouselProps) {
    let pageX = 0;

    let opacity = scrollX.interpolate({
      inputRange: [
        (pageX - width) / width,
        (pageX - width + 10) / width,
        (pageX) / width,
        (pageX + width - 250) / width,
        (pageX + width) / width,
      ],
      outputRange: [0, 0.6, 1, 0.6, 0],
      extrapolate: 'clamp',
    });

    return {
      transform: [
        {
          perspective: width,
        },
        {
          translateX: scrollX.interpolate({
            inputRange: [
              (pageX - width) / width,
              (pageX) / width,
              (pageX + width) / width,
            ],
            outputRange: [
              (-width - 1) / TR_POSITION,
              0,
              (width + 1) / TR_POSITION,
            ],
          }),
        },
        {
          rotateY: scrollX.interpolate({
            inputRange: [-1, 0, 1],
            outputRange: ['-60deg', '0deg', '60deg'],
            extrapolate: 'clamp',
          }),
        },
        {
          translateX: scrollX.interpolate({
            inputRange: [
              (pageX - width) / width,
              (pageX - width + 0.1) / width,
              pageX / width,
              (pageX + width - 0.1) / width,
              (pageX + width) / width,
            ],
            outputRange: [
              (-width - 1),
              ((-width - 1) / PESPECTIVE),
              0,
              ((width + 1) / PESPECTIVE),
              (+width + 1),
            ],
            extrapolate: 'clamp',
          }),
        },
      ],
      opacity: opacity,
    };
  }


  _renderItem({ item, index }) {
    return (
      <View key={index} style={[
        { height, top: 50, backgroundColor: item.color },
      ]}>{item.title}</View>
    );
  }

  render() {
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>


        <Carousel
          firstItem={1}
          containerCustomStyle={{ width }}
          data={data}
          useScrollView={true}
          renderItem={this._renderItem}
          sliderWidth={width}
          itemWidth={width}
          scrollInterpolator={this._scrollInterpolator}
          slideInterpolatedStyle={this._animatedStyles}
        />


      </View>
    );
  }

}

zek avatar May 09 '19 21:05 zek

Hi @zek,

Can you please put all this in a Snack example? It will make it easier for us to help you :-)

bd-arc avatar May 11 '19 07:05 bd-arc

Here is the snack https://snack.expo.io/@drtzack/paranoid-soda

zek avatar May 14 '19 16:05 zek

you make done feature

DungBuiDeveloper avatar Nov 05 '19 06:11 DungBuiDeveloper

hey did any one hava an idea how we can do it with a flatlist

khalidos32 avatar Dec 15 '19 12:12 khalidos32

Do you need to complete this job? I am a 3d-cube fullstack developer. If you hire me I will best

Sent from Mailhttps://go.microsoft.com/fwlink/?LinkId=550986 for Windows 10

From: khalid aoussarmailto:[email protected] Sent: Sunday, December 15, 2019 8:20 PM To: archriss/react-native-snap-carouselmailto:[email protected] Cc: michele jamesmailto:[email protected]; Manualmailto:[email protected] Subject: Re: [archriss/react-native-snap-carousel] 3D Cube Animation (#518)

hey did any one hava an idea how we can do it with a flatlist

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHubhttps://github.com/archriss/react-native-snap-carousel/issues/518?email_source=notifications&email_token=ANZADAT3JYPCRHSTWGITNN3QYYOJRA5CNFSM4HL43KXKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEG4X4XY#issuecomment-565804639, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ANZADAQGCNK5J2ALA2OE7WTQYYOJRANCNFSM4HL43KXA.

ghost avatar Dec 15 '19 12:12 ghost

Try this: https://snack.expo.io/@romeobalta/3d-cube-snap

romeo-balta avatar Feb 27 '20 17:02 romeo-balta

I'm having a similar issue where the selected item just disappears. Below is my _slideInterpolatedStyle. If perspective is removed, everything seems to work fine... Any clue on how I could fix this?

_slideInterpolatedStyle = (index, animatedValue, carouselProps) => ({
    opacity: animatedValue.interpolate({
      inputRange: [-1, 0, 1],
      outputRange: [0.5, 1, 0.5],
      extrapolate: 'clamp',
    }),
    transform: [
      {
        perspective: animatedValue.interpolate({
          inputRange: [-1, 0, 1],
          outputRange: [-1500, 0, -1500],
          extrapolate: 'clamp',
        }),
      },
      {
        translateX: animatedValue.interpolate({
          inputRange: [-3, -2, -1, 0, 1, 2, 3],
          outputRange: [110, 50, 0, 0, 0, -50, -110],
          extrapolate: 'clamp',
        }),
      },
    ],
  });

anshul-kai avatar Mar 13 '20 14:03 anshul-kai

Sorry, please allow me to advertise for my open source library! ~ I think this library react-native-reanimated-carousel will solve your problem. It is a high performance and very simple component, complete with React-Native reanimated 2

dohooo avatar Oct 08 '21 05:10 dohooo

Try this: https://snack.expo.io/@romeobalta/3d-cube-snap

@romeo-balta

It is exactly what we are looking for. Thanks very much. I tried writing it as a basic Flatlist/ScrollView but it didn't work as expected. Can you help me implement a Cube Animation with a basic Flatlist/ScrollView?

I wait for your response.

000xuandu avatar Jan 09 '22 10:01 000xuandu