The complete code for the tutorial is below. In this tutorial, you will learn how about
1. Different coordinate system with FlexBox properties
2. Scrollview animation with image 3D view
3. Scrollview indicator
4. Transform text object using translateY as we scroll the view
See the end result first
1. Different coordinate system with FlexBox properties
In our simple app, the parent container is given flex:1. This flex property occupies the whole view and put the subview in a column or vertically. In our parent view, we have three subviews textArea, scrollContainer, and indicatorContainer. Within these three subviews, everything is laid out vertically on y-axis by default. Our primary axis is the y-axis and the secondary axis is the x-axis.
Because default flexDirection is "column" and justifyContent is "flex-start", so everything by default is put at the beginning of each subview or sub-containers vertically. But we apply
See the code
container: {
flex: 1,
alignItems: "center",
justifyContent: "center"
},
Since we apply alignItems and justifyContent to "center", hence everything sits inside the parent container and occupies available space as much as possible based on their content size.
See the below picture to get better understanding.
import React, { useRef } from "react";
import {
SafeAreaView,
ScrollView,
StyleSheet,
View,
Animated,
useWindowDimensions,
Image
} from "react-native";
const images = [
{id:1, img:require("../assets/photo1.jpeg"), title:"Beautiful Coral Reef", color:"#33ccff"},
{id:2, img:require("../assets/photo2.jpeg"), title:"Beautiful Sea Wave", color:"brown"},
{id:3, img:require("../assets/photo3.jpeg"), title:"Ice Galcier Mystery", color:"#33ccff"},
{id:4, img:require("../assets/photo4.jpeg"), title:"Wonderful Jelly fish Group",color:"#33ccff"},
{id:5, img:require("../assets/photo5.jpeg"), title:"Fresh Sea Water", color:"#33ccff"},
{id:6, img:require("../assets/photo6.jpeg"), title:"Sea the Universe", color:"brown"},
]
export default BasicSlider = () => {
const scrollX = useRef(new Animated.Value(0)).current;
let { width: windowWidth, height:windowHeight } = useWindowDimensions();
windowHeight=windowHeight-300;
return (
<SafeAreaView style={styles.container}>
<View style={styles.textAreaContainer}>
{images.map((image, imageIndex)=>{
const inputRange=[
windowWidth*(imageIndex-1),
windowWidth*(imageIndex),
windowWidth*(imageIndex+1),
];
return(
<Animated.Text style={[styles.textView, {transform:[
{translateY:scrollX.interpolate({
inputRange,
outputRange:[-500, -50, 0],
})}
]},{
opacity:scrollX.interpolate({
inputRange,
outputRange:[0, 1, 0]
})
}, {
color:image.color
}]}>
{image.title}
</Animated.Text>
);
})}
</View>
<View style={[styles.scrollContainer, {height:windowHeight} ]}>
<ScrollView
horizontal={true}
style={styles.scrollViewStyle}
pagingEnabled
showsHorizontalScrollIndicator={false}
onScroll={Animated.event(
[{nativeEvent: {contentOffset: {x: scrollX}}}],
{useNativeDriver: false}
)}
scrollEventThrottle={16}
>
{images.map((image, imageIndex) => {
return (
<Animated.View
style={{ width: windowWidth,}}
key={imageIndex}
>
<Image source={image.img} style={styles.card} />
</Animated.View>
);
})}
</ScrollView>
</View>
<View style={styles.indicatorContainer}>
{
images.map((image, imageIndex)=>{
const width=scrollX.interpolate({
inputRange:[
windowWidth*(imageIndex-1),
windowWidth*(imageIndex),
windowWidth*(imageIndex+1),
],
outputRange:[8, 16, 8],
extrapolate:"clamp",
})
return(
<Animated.View style={[styles.normalDots, {width}, {backgroundColor:image.color}]}/>
);
})
}
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center"
},
scrollContainer: {
shadowColor:"#6A6C6E",
shadowOffset:{
width:10,
height:-10,
},
shadowOpacity:1,
},
card: {
flex: 1,
marginVertical: 10,
width:350,
overflow: "hidden",
alignSelf:"center",
},
indicatorContainer:{
flexDirection:"row",
justifyContent:"center",
alignItems:"center"
},
normalDots:{
width:8,
height:8,
borderRadius:4,
marginHorizontal:4,
},
textAreaContainer:{
width:"100%",
marginBottom:10,
},
textView:{
position:"absolute",
fontSize:22,
fontFamily:"Avenir",
fontWeight:"600",
textAlign:"center",
width:"100%"
}
});