@principal-ai/file-city-react 0.5.12 → 0.5.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -569,7 +569,7 @@ function AnimatedCamera({ citySize, isFlat, focusTarget }) {
|
|
|
569
569
|
const { camera } = useThree();
|
|
570
570
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
571
571
|
const controlsRef = useRef(null);
|
|
572
|
-
|
|
572
|
+
const prevTargetRef = useRef(null);
|
|
573
573
|
const isAnimatingRef = useRef(false);
|
|
574
574
|
// Animated camera position and target
|
|
575
575
|
const targetPos = useMemo(() => {
|
|
@@ -598,17 +598,9 @@ function AnimatedCamera({ citySize, isFlat, focusTarget }) {
|
|
|
598
598
|
targetZ: 0,
|
|
599
599
|
};
|
|
600
600
|
}, [focusTarget, isFlat, citySize]);
|
|
601
|
-
//
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
if (controlsRef.current) {
|
|
605
|
-
controlsRef.current.target.set(targetPos.targetX, targetPos.targetY, targetPos.targetZ);
|
|
606
|
-
controlsRef.current.update();
|
|
607
|
-
}
|
|
608
|
-
// Only run on mount
|
|
609
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
610
|
-
}, []);
|
|
611
|
-
// Spring animation for camera movement (only for subsequent changes)
|
|
601
|
+
// Create a stable key to detect when target actually changes
|
|
602
|
+
const targetKey = `${targetPos.x},${targetPos.y},${targetPos.z},${targetPos.targetX},${targetPos.targetZ}`;
|
|
603
|
+
// Spring animation for camera movement
|
|
612
604
|
const { camX, camY, camZ, lookX, lookY, lookZ } = useSpring({
|
|
613
605
|
camX: targetPos.x,
|
|
614
606
|
camY: targetPos.y,
|
|
@@ -617,6 +609,7 @@ function AnimatedCamera({ citySize, isFlat, focusTarget }) {
|
|
|
617
609
|
lookY: targetPos.targetY,
|
|
618
610
|
lookZ: targetPos.targetZ,
|
|
619
611
|
config: { tension: 60, friction: 20 },
|
|
612
|
+
immediate: prevTargetRef.current === null, // Skip animation on first render
|
|
620
613
|
onStart: () => {
|
|
621
614
|
isAnimatingRef.current = true;
|
|
622
615
|
},
|
|
@@ -624,14 +617,20 @@ function AnimatedCamera({ citySize, isFlat, focusTarget }) {
|
|
|
624
617
|
isAnimatingRef.current = false;
|
|
625
618
|
},
|
|
626
619
|
});
|
|
627
|
-
//
|
|
628
|
-
|
|
620
|
+
// Track target changes
|
|
621
|
+
useEffect(() => {
|
|
622
|
+
prevTargetRef.current = targetKey;
|
|
623
|
+
}, [targetKey]);
|
|
624
|
+
// Update camera each frame while animating or on first frame
|
|
629
625
|
useFrame(() => {
|
|
630
|
-
if (!controlsRef.current
|
|
626
|
+
if (!controlsRef.current)
|
|
631
627
|
return;
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
628
|
+
// On first frame or while animating, update camera from spring values
|
|
629
|
+
if (prevTargetRef.current === null || isAnimatingRef.current) {
|
|
630
|
+
camera.position.set(camX.get(), camY.get(), camZ.get());
|
|
631
|
+
controlsRef.current.target.set(lookX.get(), lookY.get(), lookZ.get());
|
|
632
|
+
controlsRef.current.update();
|
|
633
|
+
}
|
|
635
634
|
});
|
|
636
635
|
const resetToInitial = useCallback(() => {
|
|
637
636
|
const targetHeight = isFlat ? citySize * 1.5 : citySize * 1.1;
|
package/package.json
CHANGED
|
@@ -996,7 +996,7 @@ function AnimatedCamera({ citySize, isFlat, focusTarget }: AnimatedCameraProps)
|
|
|
996
996
|
const { camera } = useThree();
|
|
997
997
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
998
998
|
const controlsRef = useRef<any>(null);
|
|
999
|
-
|
|
999
|
+
const prevTargetRef = useRef<string | null>(null);
|
|
1000
1000
|
const isAnimatingRef = useRef(false);
|
|
1001
1001
|
|
|
1002
1002
|
// Animated camera position and target
|
|
@@ -1027,18 +1027,10 @@ function AnimatedCamera({ citySize, isFlat, focusTarget }: AnimatedCameraProps)
|
|
|
1027
1027
|
};
|
|
1028
1028
|
}, [focusTarget, isFlat, citySize]);
|
|
1029
1029
|
|
|
1030
|
-
//
|
|
1031
|
-
|
|
1032
|
-
camera.position.set(targetPos.x, targetPos.y, targetPos.z);
|
|
1033
|
-
if (controlsRef.current) {
|
|
1034
|
-
controlsRef.current.target.set(targetPos.targetX, targetPos.targetY, targetPos.targetZ);
|
|
1035
|
-
controlsRef.current.update();
|
|
1036
|
-
}
|
|
1037
|
-
// Only run on mount
|
|
1038
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1039
|
-
}, []);
|
|
1030
|
+
// Create a stable key to detect when target actually changes
|
|
1031
|
+
const targetKey = `${targetPos.x},${targetPos.y},${targetPos.z},${targetPos.targetX},${targetPos.targetZ}`;
|
|
1040
1032
|
|
|
1041
|
-
// Spring animation for camera movement
|
|
1033
|
+
// Spring animation for camera movement
|
|
1042
1034
|
const { camX, camY, camZ, lookX, lookY, lookZ } = useSpring({
|
|
1043
1035
|
camX: targetPos.x,
|
|
1044
1036
|
camY: targetPos.y,
|
|
@@ -1047,6 +1039,7 @@ function AnimatedCamera({ citySize, isFlat, focusTarget }: AnimatedCameraProps)
|
|
|
1047
1039
|
lookY: targetPos.targetY,
|
|
1048
1040
|
lookZ: targetPos.targetZ,
|
|
1049
1041
|
config: { tension: 60, friction: 20 },
|
|
1042
|
+
immediate: prevTargetRef.current === null, // Skip animation on first render
|
|
1050
1043
|
onStart: () => {
|
|
1051
1044
|
isAnimatingRef.current = true;
|
|
1052
1045
|
},
|
|
@@ -1055,14 +1048,21 @@ function AnimatedCamera({ citySize, isFlat, focusTarget }: AnimatedCameraProps)
|
|
|
1055
1048
|
},
|
|
1056
1049
|
});
|
|
1057
1050
|
|
|
1058
|
-
//
|
|
1059
|
-
|
|
1051
|
+
// Track target changes
|
|
1052
|
+
useEffect(() => {
|
|
1053
|
+
prevTargetRef.current = targetKey;
|
|
1054
|
+
}, [targetKey]);
|
|
1055
|
+
|
|
1056
|
+
// Update camera each frame while animating or on first frame
|
|
1060
1057
|
useFrame(() => {
|
|
1061
|
-
if (!controlsRef.current
|
|
1058
|
+
if (!controlsRef.current) return;
|
|
1062
1059
|
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1060
|
+
// On first frame or while animating, update camera from spring values
|
|
1061
|
+
if (prevTargetRef.current === null || isAnimatingRef.current) {
|
|
1062
|
+
camera.position.set(camX.get(), camY.get(), camZ.get());
|
|
1063
|
+
controlsRef.current.target.set(lookX.get(), lookY.get(), lookZ.get());
|
|
1064
|
+
controlsRef.current.update();
|
|
1065
|
+
}
|
|
1066
1066
|
});
|
|
1067
1067
|
|
|
1068
1068
|
const resetToInitial = useCallback(() => {
|