React Native Reanimated2 TimePicker Typescript
Reanimated2 TimePicker Typescript 반응 네이티브
const screenHeight = 280
const textHeight = 56
interface TimePickerPropsInterface {
backgroundColor: string
startHourValue: number
startMinuteValue: number
hourValueChanged: (hour: number) => void
minuteValueChanged: (minute: number) => void
}
const styles = StyleSheet.create({
container: {
flexDirection: "row",
height: screenHeight,
marginTop: 150,
},
})
const animatedContainerLeftStyle: ViewStyle = {
position: "absolute",
left: 0,
right: Dimensions.get("screen").width / 2,
top: 0,
opacity: 0.5,
height: screenHeight,
}
const animatedContainerRightStyle: ViewStyle = {
position: "absolute",
left: Dimensions.get("screen").width / 2,
right: 0,
top: 0,
height: screenHeight,
opacity: 0.5,
}
const visualContainerRightStyle: ViewStyle = {
alignItems: "center",
marginRight: 20,
flex: 1,
}
const visualContainerLeftStyle: ViewStyle = {
alignItems: "center",
marginLeft: 20,
flex: 1,
}
const basicTextStyle: TextStyle = {
fontSize: 52,
height: textHeight,
color: palette.darkGreen,
lineHeight: 59,
}
const backgroundAbove: ViewStyle = {
backgroundColor: "#fff",
opacity: 1,
top: -textHeight - 20,
height: textHeight + 20,
width: "100%",
position: "absolute",
}
const backgroundBelow: ViewStyle = {
backgroundColor: "#fff",
opacity: 1,
bottom: -textHeight - 25,
height: textHeight + 25,
width: "100%",
position: "absolute",
}
const gradientBottom: ViewStyle = {
height: textHeight - 10,
width: "100%",
bottom: 0,
position: "absolute",
}
const gradientTop: ViewStyle = {
height: textHeight - 10,
width: "100%",
top: 0,
position: "absolute",
}
const centerView: ViewStyle = {
height: textHeight,
borderTopWidth: 0.5,
borderBottomWidth: 0.5,
flex: 1,
justifyContent: "center",
alignItems: "center",
position: "absolute",
top: screenHeight / 2 - textHeight / 2,
right: -20,
left: -20,
}
const BOX1: ViewStyle = {
flex: 1,
justifyContent: "center",
alignItems: "center",
}
const TEXTSTYLE: TextStyle = {
color: "black",
fontSize: 52,
alignSelf: "center",
lineHeight: 52,
textAlign: "center",
}
export const TimePicker: React.FC<TimePickerPropsInterface> = (props) => {
const hourOffset = props.startHourValue * textHeight
const minuteOffset = props.startMinuteValue * textHeight
const hourSavedValue = useSharedValue(-1)
const minuteSavedValue = useSharedValue(-1)
const yL = useSharedValue(hourOffset)
const yR = useSharedValue(minuteOffset)
const textNumberOffset = (screenHeight - textHeight) / 2
const translateYHour = useAnimatedStyle(() => {
return {
transform: [{ translateY: textNumberOffset - yL.value }],
}
})
const translateYMinute = useAnimatedStyle(() => {
return {
transform: [{ translateY: textNumberOffset - yR.value }],
}
})
const scrollL = useAnimatedScrollHandler({
onScroll: (e) => {
yL.value = e.contentOffset.y
},
})
const scrollR = useAnimatedScrollHandler({
onScroll: (e) => {
yR.value = e.contentOffset.y
},
})
const indexTextLeft = useDerivedValue(() => {
const i = Math.round(yL.value / textHeight)
hourSavedValue.value = i
if (i !== hourSavedValue.value) {
hourSavedValue.value = i
runOnJS(ReactNativeHaptic.generate)("notification")
}
return i
})
const indexTextRight = useDerivedValue(() => {
const i = Math.round(yR.value / textHeight)
if (i !== minuteSavedValue.value) {
minuteSavedValue.value = i
runOnJS(ReactNativeHaptic.generate)("notification")
}
return i
})
return (
<View style={[styles.container, { backgroundColor: props.backgroundColor }]}>
{/* HOUR */}
<Animated.View style={[visualContainerLeftStyle, translateYHour]}>
{TimeHourTexts.map((c, i) => (
<OpacityNumber
i={i}
y={yL}
index={indexTextLeft}
text={c.text}
key={c.text}
></OpacityNumber>
))}
</Animated.View>
<Animated.ScrollView
onScroll={scrollL}
contentOffset={{ y: hourOffset, x: 0 }}
style={animatedContainerLeftStyle}
snapToInterval={textHeight}
scrollEventThrottle={1}
showsVerticalScrollIndicator={false}
contentContainerStyle={{
height: screenHeight - textHeight + textHeight * TimeHourTexts.length,
}}
decelerationRate="normal"
onMomentumScrollEnd={() => {
props.hourValueChanged(indexTextLeft.value)
}}
></Animated.ScrollView>
{/* MINUTE */}
<Animated.View style={[visualContainerRightStyle, translateYMinute]}>
{TimeMinutesTexts.map((c, i) => (
<OpacityNumber
i={i}
y={yR}
index={indexTextRight}
text={c.text}
key={c.text}
></OpacityNumber>
))}
</Animated.View>
<Animated.ScrollView
onScroll={scrollR}
contentOffset={{ y: minuteOffset, x: 0 }}
style={animatedContainerRightStyle}
snapToInterval={textHeight}
scrollEventThrottle={1}
showsVerticalScrollIndicator={false}
contentContainerStyle={{
height: screenHeight - textHeight + textHeight * TimeMinutesTexts.length,
}}
decelerationRate="normal"
onMomentumScrollEnd={() => {
props.minuteValueChanged(indexTextRight.value)
}}
></Animated.ScrollView>
<View
style={[
backgroundAbove,
{
backgroundColor: props.backgroundColor,
},
]}
></View>
<View
style={[
backgroundBelow,
{
backgroundColor: props.backgroundColor,
},
]}
></View>
<LinearGradient
pointerEvents="none"
colors={[rgba(props.backgroundColor, 0), props.backgroundColor]}
style={gradientBottom}
></LinearGradient>
<LinearGradient
pointerEvents="none"
colors={[props.backgroundColor, rgba(props.backgroundColor, 0)]}
style={gradientTop}
></LinearGradient>
<View
style={[
centerView,
{
borderTopColor: rgba("black", 0.3),
borderBottomColor: rgba("black", 0.3),
},
]}
pointerEvents="none"
>
<View style={BOX1}>
<Text preset="h1" style={TEXTSTYLE}>
:
</Text>
</View>
</View>
</View>
)
}
interface Props {
y: Animated.SharedValue<number>
// y: number
index: Animated.SharedValue<number>
i: number
text: string
}
export const OpacityNumber: React.FC<Props> = ({ y, index, i, text }) => {
const previousPosition = (i - 1) * textHeight
const currentPosition = i * textHeight
const nextPosition = (i + 1) * textHeight
const style = useAnimatedStyle(() => {
const op = interpolate(
y.value,
[previousPosition, currentPosition, nextPosition],
[0.3, 1, 0.3],
Extrapolate.CLAMP,
)
const calc = index.value > i + 2 ? 0 : index.value < i - 2 ? 0 : op
return {
opacity: calc,
}
})
return (
<Animated.View style={style} key={text}>
<Text preset="h1" style={basicTextStyle} key={text}>
{text}
</Text>
</Animated.View>
)
}
Reference
이 문제에 관하여(React Native Reanimated2 TimePicker Typescript), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/xemil/react-native-reanimated2-timepicker-typescript-3o6j텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)