89 lines
2.6 KiB
TypeScript
89 lines
2.6 KiB
TypeScript
import { FC } from "react";
|
|
import { View, Text, ScrollView, useWindowDimensions } from "react-native";
|
|
import { ExGridViewItem } from "./ExGridViewItem";
|
|
import Animated, {
|
|
useAnimatedStyle,
|
|
useSharedValue,
|
|
} from "react-native-reanimated";
|
|
import { Gesture, GestureDetector } from "react-native-gesture-handler";
|
|
|
|
export const ExGridView: FC<{
|
|
data: {
|
|
trainNumber: string;
|
|
array: string;
|
|
name: string;
|
|
type: string;
|
|
time: string;
|
|
}[];
|
|
}> = ({ data }) => {
|
|
const groupedData = {};
|
|
const groupKeys = [];
|
|
|
|
const { width } = useWindowDimensions();
|
|
data.forEach((item) => {
|
|
const hour = item.time.split(":")[0];
|
|
if (!groupedData[hour]) {
|
|
groupedData[hour] = [];
|
|
groupKeys.push(hour);
|
|
}
|
|
groupedData[hour].push(item);
|
|
});
|
|
// ドラッグ位置を保持する共有値
|
|
const widthX = useSharedValue(width);
|
|
const savedWidthX = useSharedValue(width);
|
|
|
|
// パンジェスチャー(ドラッグ)のハンドラー
|
|
const pinchGesture = Gesture.Pinch()
|
|
.onUpdate((e) => {
|
|
const calc = savedWidthX.value * e.scale;
|
|
widthX.value = calc > width ? calc : width;
|
|
})
|
|
.onEnd(() => {
|
|
savedWidthX.value = widthX.value;
|
|
});
|
|
// アニメーションスタイル
|
|
const animatedStyle = useAnimatedStyle(() => ({
|
|
width: widthX.value,
|
|
}));
|
|
return (
|
|
<GestureDetector gesture={pinchGesture}>
|
|
<ScrollView horizontal nestedScrollEnabled pinchGestureEnabled={false}>
|
|
<Animated.ScrollView
|
|
style={[{ backgroundColor: "white", width: width }, animatedStyle]}
|
|
pinchGestureEnabled={false}
|
|
minimumZoomScale={0.5}
|
|
maximumZoomScale={3.0}
|
|
stickyHeaderIndices={
|
|
groupKeys.at(0) ? groupKeys.map((_, i) => i * 2) : []
|
|
}
|
|
>
|
|
{groupKeys.map((hour) => [
|
|
<View
|
|
style={{
|
|
backgroundColor: "white",
|
|
padding: 5,
|
|
borderBottomWidth: 0.5,
|
|
borderTopWidth: 0.5,
|
|
borderBottomColor: "#ccc",
|
|
}}
|
|
key={hour}
|
|
>
|
|
<Text style={{ fontSize: 15 }}>{hour}時台</Text>
|
|
</View>,
|
|
<View style={{ flexDirection: "row", position: "relative" }}>
|
|
{groupedData[hour].map((d, i) => (
|
|
<ExGridViewItem
|
|
key={d.trainNumber + i}
|
|
d={d}
|
|
index={i}
|
|
width={widthX}
|
|
/>
|
|
))}
|
|
</View>,
|
|
])}
|
|
</Animated.ScrollView>
|
|
</ScrollView>
|
|
</GestureDetector>
|
|
);
|
|
};
|