98 lines
2.6 KiB
TypeScript
98 lines
2.6 KiB
TypeScript
import React, { useEffect } from "react";
|
|
import { useItemContext } from "react-native-sortables";
|
|
import Animated, {
|
|
interpolate,
|
|
useAnimatedStyle,
|
|
useSharedValue,
|
|
withDelay,
|
|
withSpring,
|
|
} from "react-native-reanimated";
|
|
import { GridMiniSign } from "./GridMiniSign";
|
|
|
|
type Props = {
|
|
item: any;
|
|
cellW: number;
|
|
cellH: number;
|
|
startX: number; // 入場開始位置(カルーセル上の元座標)
|
|
startY: number;
|
|
exitX: number; // 退場先位置(タップ選択後のカルーセル座標)
|
|
exitY: number;
|
|
startScale: number;
|
|
isExiting: boolean;
|
|
exitDelay: number;
|
|
onPress?: () => void;
|
|
};
|
|
|
|
/** カルーセル中央 → グリッドセルへ飛ぶアニメーション付きカード */
|
|
export const SortGridCard = React.memo(function SortGridCard({
|
|
item,
|
|
cellW,
|
|
cellH,
|
|
startX,
|
|
startY,
|
|
exitX,
|
|
exitY,
|
|
startScale,
|
|
isExiting,
|
|
exitDelay,
|
|
onPress,
|
|
}: Props) {
|
|
const { activationAnimationProgress } = useItemContext();
|
|
|
|
const tx = useSharedValue(startX);
|
|
const ty = useSharedValue(startY);
|
|
const sc = useSharedValue(startScale);
|
|
|
|
// 入場: カルーセル位置からグリッドセル位置へ
|
|
useEffect(() => {
|
|
tx.value = withSpring(0, { damping: 16, stiffness: 110 });
|
|
ty.value = withSpring(0, { damping: 16, stiffness: 110 });
|
|
sc.value = withSpring(1, { damping: 16, stiffness: 110 });
|
|
}, []);
|
|
|
|
// 退場: グリッドセル位置からカルーセル位置へ戻る
|
|
useEffect(() => {
|
|
if (!isExiting) return;
|
|
tx.value = withDelay(exitDelay, withSpring(exitX, { damping: 16, stiffness: 110 }));
|
|
ty.value = withDelay(exitDelay, withSpring(exitY, { damping: 16, stiffness: 110 }));
|
|
sc.value = withDelay(exitDelay, withSpring(startScale, { damping: 16, stiffness: 110 }));
|
|
}, [isExiting]);
|
|
|
|
const animStyle = useAnimatedStyle(() => {
|
|
const p = activationAnimationProgress.value;
|
|
return {
|
|
opacity: interpolate(p, [0, 1], [1, 0.85]),
|
|
shadowOpacity: interpolate(p, [0, 1], [0, 0.4]),
|
|
shadowRadius: interpolate(p, [0, 1], [0, 10]),
|
|
elevation: interpolate(p, [0, 1], [1, 12]),
|
|
transform: [
|
|
{ translateX: tx.value },
|
|
{ translateY: ty.value },
|
|
{ scale: sc.value * interpolate(p, [0, 1], [1, 1.06]) },
|
|
] as any,
|
|
};
|
|
});
|
|
|
|
return (
|
|
<Animated.View
|
|
style={[
|
|
{
|
|
width: cellW,
|
|
height: cellH,
|
|
shadowColor: "#000",
|
|
shadowOffset: { width: 0, height: 4 },
|
|
},
|
|
animStyle,
|
|
]}
|
|
>
|
|
<GridMiniSign
|
|
item={item}
|
|
width={cellW}
|
|
height={cellH}
|
|
onPress={onPress}
|
|
/>
|
|
</Animated.View>
|
|
);
|
|
});
|
|
|