My cards here work from right to left with a nice animation. But when the animation rewinds, the card positions rewind and there is no infinite animation image. What I want is for the first card to enter again as the last card leaves the screen and infinity occurs. how do i do this? As you can see in the gif, the animation ends and I want the last element to exit from the left of the screen and the first element to enter again.
import React, { useEffect, useRef } from 'react';
import { Animated, StyleSheet, Text, View, Dimensions, Image } from 'react-native';
import anonim_icon from "../img/anonim.png";
const cardData = [
{ id: 0, title: "Feeling Happy" },
{ id: 1, title: "Feeling Calm" },
{ id: 2, title: "Feeling Angry" },
{ id: 3, title: "Feeling Sad" },
];
const App = () => {
const translateX = useRef(new Animated.Value(width)).current;
const Cards = ({ item, index }) => {
return (
<View style={styles.cards_con} key={index}>
<Image
style={styles.cards_ico}
source={anonim_icon}
resizeMode="contain"
/>
<Text style={styles.card_title}>{item.title}</Text>
</View>
);
};
useEffect(() => {
const startAnimation = () => {
translateX.setValue(width); // Animasyon başlangıç pozisyonu (sağ dışı)
Animated.loop(
Animated.sequence([
Animated.timing(translateX, {
toValue: -width * cardData.length, // Sol dışına çıkış
duration: 17000, // Hareket süresi
useNativeDriver: true,
}),
]),
).start();
};
startAnimation();
}, [translateX, width]);
return (
<View style={styles.container}>
<Animated.View
style={{
flexDirection: 'row',
transform: [{ translateX }],
}}
>
<View style={{ width: width * 3 }}/>
{cardData.map((item, index) => (
<Cards key={index} item={item} index={index} />
))}
</Animated.View>
</View>
);
};
const { width, height } = Dimensions.get('window');
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#000",
},
cards_con: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-around",
backgroundColor: "#323232",
height: height / 13,
borderRadius: 10,
marginHorizontal: 10,
padding: 10,
width: width / 1.7,
},
cards_ico: {
width: 30,
height: 30,
borderRadius: 10,
},
card_title: {
color: "#FFFFFF",
marginLeft: 10,
fontSize: 16,
},
});
export default App;
here's the modified code.
Changes I had to do to achieve your effect:
Make sure you add your image/icon back as I did not have the file, I removed the Icon/Image code and CSS for debugging.
import React, { useEffect, useRef } from 'react';
import { Animated, StyleSheet, Text, View, Dimensions } from 'react-native';
const cardData = [
{ id: 0, title: "Feeling Happy" },
{ id: 1, title: "Feeling Calm" },
{ id: 2, title: "Feeling Angry" },
{ id: 3, title: "Feeling Sad" },
];
const App = () => {
const translateX = useRef(new Animated.Value(0)).current;
const { width } = Dimensions.get('window');
const Cards = ({ item }) => {
return (
<View style={styles.cards_con}>
<Text style={styles.card_title}>{item.title}</Text>
</View>
);
};
useEffect(() => {
const cardWidth = 220; // Width of card + horizontal margin
const contentWidth = cardWidth * cardData.length;
const startAnimation = () => {
translateX.setValue(0); // Reset to start position
Animated.sequence([
Animated.timing(translateX, {
toValue: -contentWidth,
duration: 17000,
useNativeDriver: true,
}),
// Reset the position instantly
Animated.timing(translateX, {
toValue: 0,
duration: 0,
useNativeDriver: true,
})
]).start(() => {
// Restart the animation when complete
startAnimation();
});
};
startAnimation();
return () => {
// Cleanup animation when component unmounts
translateX.stopAnimation();
};
}, []);
return (
<View style={styles.container}>
<View style={styles.clipContainer}>
<Animated.View
style={{
flexDirection: 'row',
transform: [{ translateX }],
}}
>
{/* Original set of cards */}
{cardData.map((item, index) => (
<Cards key={`original-${index}`} item={item} />
))}
{/* Duplicate set for seamless transition */}
{cardData.map((item, index) => (
<Cards key={`duplicate-${index}`} item={item} />
))}
</Animated.View>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#000",
},
clipContainer: {
overflow: 'hidden',
width: '100%',
},
cards_con: {
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
backgroundColor: "#323232",
height: 50,
borderRadius: 10,
marginHorizontal: 10,
padding: 10,
width: 200,
},
card_title: {
color: "#FFFFFF",
fontSize: 16,
},
});
export default App;