diff --git a/components/StationDiagram/ExGridView.tsx b/components/StationDiagram/ExGridView.tsx index 2d1e573..183fdf4 100644 --- a/components/StationDiagram/ExGridView.tsx +++ b/components/StationDiagram/ExGridView.tsx @@ -1,13 +1,29 @@ import { FC, useRef, useState, useCallback } from "react"; -import { View, Text, ScrollView, useWindowDimensions } from "react-native"; +import { + View, + Text, + ScrollView, + useWindowDimensions, + Vibration, +} from "react-native"; import { ExGridViewItem } from "./ExGridViewItem"; import Animated, { useAnimatedStyle, useSharedValue, runOnJS, useAnimatedScrollHandler, + withTiming, + Easing, + FadeIn, + FadeOut, + BounceInUp, + FadeInUp, + FadeOutUp, } from "react-native-reanimated"; import { Gesture, GestureDetector } from "react-native-gesture-handler"; +import { ExGridViewTimePositionItem } from "./ExGridViewTimePositionItem"; +import { useCurrentTrain } from "@/stateBox/useCurrentTrain"; +import dayjs from "dayjs"; export const ExGridView: FC<{ data: { @@ -18,21 +34,48 @@ export const ExGridView: FC<{ time: string; }[]; }> = ({ data }) => { - const groupedData = {}; - const groupKeys = []; + const groupedData: { + [d: number]: { + trainNumber: string; + array: string; + name: string; + type: string; + time: string; + isOperating: boolean; + }[]; + } = {}; + const groupKeys: string[] = []; const { width } = useWindowDimensions(); + const { currentTrain } = useCurrentTrain(); data.forEach((item) => { - const hour = item.time.split(":")[0]; + let isOperating = false; + let [hour, minute] = item.time.split(":"); + if (currentTrain.findIndex((x) => x.num == item.trainNumber) != -1) { + const currentTrainTime = currentTrain.find( + (x) => x.num == item.trainNumber + )?.delay; + if (currentTrainTime != "入線") { + [hour, minute] = dayjs() + .hour(parseInt(hour)) + .minute(parseInt(minute)) + .add(parseInt(currentTrainTime), "minute") + .format("H:m") + .split(":"); + } + isOperating = true; + } if (!groupedData[hour]) { groupedData[hour] = []; groupKeys.push(hour); } - groupedData[hour].push(item); + groupedData[hour].push({ ...item, time: `${hour}:${minute}`, isOperating }); }); // ドラッグ位置を保持する共有値 const widthX = useSharedValue(width); const savedWidthX = useSharedValue(width); + const isChanging = useSharedValue(false); + const animationProgress = useSharedValue(0); // アニメーション進行度 const [scrollEnabled, setScrollEnabled] = useState(true); const scrollRef = useRef(null); @@ -55,21 +98,41 @@ export const ExGridView: FC<{ const gesture = Gesture.Pan() .minPointers(2) // 最低2本指 .maxPointers(2) // 最大2本指 - .onTouchesDown((e) => { - if (e.numberOfTouches >= 2) runOnJS(toggleScrollEnabled)(false); + .onStart(() => { + runOnJS(toggleScrollEnabled)(false); }) - .onTouchesUp((e) => { - runOnJS(toggleScrollEnabled)(true); - }) - .onEnd((e) => { + .onEnd(() => { runOnJS(toggleScrollEnabled)(true); + savedWidthX.value = widthX.value; }); + const longPressGesture = Gesture.Pan() + .minPointers(1) + .maxPointers(1) + .activateAfterLongPress(200) + .onStart(() => { + runOnJS(Vibration.vibrate)(30); + isChanging.value = true; + }) + .onUpdate((e) => { + const calc = widthX.value + e.velocityY; + widthX.value = calc > width ? calc : width; + }) + .onEnd(() => { + console.log("Long press ended"); + isChanging.value = false; + }); + // ジェスチャーを組み合わせる - const composed = Gesture.Simultaneous(pinchGesture, gesture); + const composed = Gesture.Simultaneous( + longPressGesture, + pinchGesture, + gesture + ); // アニメーションスタイル const animatedStyle = useAnimatedStyle(() => ({ width: widthX.value, + backgroundColor: isChanging.value ? "#8adeffff" : "white", })); // 時ヘッダーを横にスクロールしたときの処理 const scrollX = useSharedValue(0); @@ -81,120 +144,143 @@ export const ExGridView: FC<{ const stickyTextStyle = useAnimatedStyle(() => ({ transform: [{ translateX: scrollX.value }], })); + const animatedLongPressStyle = useAnimatedStyle(() => ({ + display: isChanging.value ? "flex" : "none", + })); return ( - - { - // 現在のスクロール位置を取得 - const currentScrollX = scrollX.value; - const containerWidth = width - 50; - - // コンテンツが画面からはみ出している場合のみ右端にスクロール - if (currentScrollX + containerWidth > contentWidth) { - const newScrollX = Math.max(0, contentWidth - containerWidth); - scrollRef.current?.scrollTo({ x: newScrollX, animated: true }); - } - }} - ref={scrollRef} - contentContainerStyle={{ - flexDirection: "column", - backgroundColor: "white", - }} + <> + - - {Array.from({ length: 60 }, (_, i) => i + 1).map((num) => { - if (num % 5 === 0) { - return ( - - {num - 5} - - ); - } else return <>; - })} - - (分) - - + + ↑縮小 ・ 拡大↓ + + + i * 2) : [] - } + onScroll={scrollHandler} + onContentSizeChange={(contentWidth) => { + // 現在のスクロール位置を取得 + const currentScrollX = scrollX.value; + const containerWidth = width - 50; + + // コンテンツが画面からはみ出している場合のみ右端にスクロール + if (currentScrollX + containerWidth > contentWidth) { + const newScrollX = Math.max(0, contentWidth - containerWidth); + scrollRef.current?.scrollTo({ x: newScrollX, animated: true }); + } + }} + ref={scrollRef} + contentContainerStyle={{ + flexDirection: "column", + backgroundColor: "white", + }} > - {groupKeys.map((hour) => [ - + {Array.from({ length: 60 }, (_, i) => i + 1).map((num) => { + if (num % 5 === 0) { + return ( + + {num - 5} + + ); + } else return <>; + })} + - + + i * 2) : [] + } + > + {groupKeys.map((hour) => [ + - {hour}時台 - - , - - {groupedData[hour].map((d, i,array) => ( - - ))} - , - ])} + + {hour}時台 + + , + + {groupedData[hour].map((d, i, array) => ( + + ))} + + , + ])} + - - + + ); }; diff --git a/components/StationDiagram/ExGridViewItem.tsx b/components/StationDiagram/ExGridViewItem.tsx index 59a5065..6af92f6 100644 --- a/components/StationDiagram/ExGridViewItem.tsx +++ b/components/StationDiagram/ExGridViewItem.tsx @@ -26,6 +26,7 @@ export const ExGridViewItem: FC<{ name: string; type: string; time: string; + isOperating: boolean; }; index: number; width: SharedValue; @@ -235,7 +236,7 @@ export const ExGridViewItem: FC<{ > openTrainInfo()}> - {formattedTime} + {formattedTime} ; + hour: string; +}> = ({ width, hour }) => { + const date = dayjs(); + const formattedTime = date.format("m"); + const formattedHour = date.format("H"); + + // if(typeString == "回送"){ + // return<>; + // } + const animatedStyle = useAnimatedStyle(() => { + const leftPosition = + ((((width.value - 50) / 100) * parseInt(formattedTime)) / 60) * 100; + return { + left: leftPosition, + }; + }, [formattedTime]); + if (formattedHour != hour) return <>; + return ( + + + + ); +}; diff --git a/components/StationDiagram/StationDiagramView.tsx b/components/StationDiagram/StationDiagramView.tsx index 13701e4..10dcd32 100644 --- a/components/StationDiagram/StationDiagramView.tsx +++ b/components/StationDiagram/StationDiagramView.tsx @@ -50,29 +50,35 @@ export const StationDiagramView: FC = ({ route }) => { useEffect(() => { if (allTrainDiagram && currentStation.length > 0) { const stationName = currentStation[0].Station_JP; - let returnDataArray = []; + let returnDataArray: { + trainNumber: string; + array: any; + name: any; + type: any; + time: any; + }[] = []; Object.keys(allTrainDiagram).forEach((d) => { - allTrainDiagram[d] - .split("#") - .filter((d) => { - const [station,type,time] = d.split(","); - return station === stationName; - }) - .forEach((x) => { - const [name, type, time] = x.split(","); - if (!name || !type || !time) return; - const arrayData = { - trainNumber: d, - array: allTrainDiagram[d], - name, - type, - time, - }; - // //条件によってフィルタリング - // if(type && type.includes("通")) return; - // if(type && type.includes("着")) return; - returnDataArray.push(arrayData); - }); + allTrainDiagram[d] + .split("#") + .filter((d) => { + const [station, type, time] = d.split(","); + return station === stationName; + }) + .forEach((x) => { + const [name, type, time] = x.split(","); + if (!name || !type || !time) return; + const arrayData = { + trainNumber: d, + array: allTrainDiagram[d], + name, + type, + time, + }; + // //条件によってフィルタリング + // if(type && type.includes("通")) return; + // if(type && type.includes("着")) return; + returnDataArray.push(arrayData); + }); }); setCurrentStationDiagram( returnDataArray.sort((a, b) => { @@ -105,8 +111,8 @@ export const StationDiagramView: FC = ({ route }) => { > {currentStation[0].Station_JP}駅 時刻表 - {/* */} - + {/* */} + {/*