perf: render theo nhu cầu + throttle cameraYaw (giảm tải khi đứng yên)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
tuyenio
2026-06-24 16:07:17 +07:00
parent 3ffa0d9455
commit 336e3ddb63
+31 -7
View File
@@ -958,6 +958,8 @@ function TourExperience({
const transitionLockRef = useRef(false);
const currentFovRef = useRef(DEFAULT_FOV);
const targetFovRef = useRef(DEFAULT_FOV);
const needsRenderRef = useRef(true);
const lastYawRef = useRef(0);
const lastPinchDistanceRef = useRef<number | null>(null);
const infoMarkerRefs = useRef<Map<string, HTMLButtonElement>>(new Map());
const [activeInfoMarker, setActiveInfoMarker] = useState<InfoMarker | null>(null);
@@ -1428,6 +1430,11 @@ function TourExperience({
}
};
const handleControlsChange = () => {
needsRenderRef.current = true;
};
controls.addEventListener("change", handleControlsChange);
renderer.domElement.addEventListener("wheel", handleWheel, { passive: false });
renderer.domElement.addEventListener("touchstart", handleTouchStart, { passive: false });
renderer.domElement.addEventListener("touchmove", handleTouchMove, { passive: false });
@@ -1455,8 +1462,9 @@ function TourExperience({
const animate = () => {
const targetFov = targetFovRef.current;
const fovAnimating = Math.abs(currentFovRef.current - targetFov) > 0.01;
if (Math.abs(currentFovRef.current - targetFov) > 0.01) {
if (fovAnimating) {
currentFovRef.current += (targetFov - currentFovRef.current) * 0.16;
camera.fov = currentFovRef.current;
camera.updateProjectionMatrix();
@@ -1464,20 +1472,35 @@ function TourExperience({
currentFovRef.current = targetFov;
camera.fov = targetFov;
camera.updateProjectionMatrix();
needsRenderRef.current = true;
}
if (!vrModeRef.current) {
controls.update();
}
// controls.update() trả về true khi camera vừa thay đổi (kể cả damping đang lắng).
const controlsChanged = vrModeRef.current ? false : controls.update();
const transitionActive = transitionFrameRef.current !== null;
const active =
needsRenderRef.current ||
fovAnimating ||
controlsChanged ||
controls.autoRotate ||
vrModeRef.current ||
transitionActive;
// Update camera yaw for mini-map rotation
if (!active) {
return;
}
needsRenderRef.current = false;
// Cập nhật yaw cho mini-map — chỉ setState khi đổi đủ lớn để tránh re-render thừa.
const direction = new THREE.Vector3();
camera.getWorldDirection(direction);
const yaw = yawFromDirection(direction);
setCameraYaw(yaw);
if (Math.abs(normalizeYaw(yaw - lastYawRef.current)) > 0.15) {
lastYawRef.current = yaw;
setCameraYaw(yaw);
}
updateHotspots();
renderer.render(threeScene, camera);
};
@@ -1495,6 +1518,7 @@ function TourExperience({
renderer.domElement.removeEventListener("pointermove", handlePointerMove);
renderer.domElement.removeEventListener("pointerup", handlePointerEnd);
renderer.domElement.removeEventListener("pointercancel", handlePointerEnd);
controls.removeEventListener("change", handleControlsChange);
renderer.setAnimationLoop(null);
controls.dispose();
geometry.dispose();