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:
@@ -958,6 +958,8 @@ function TourExperience({
|
|||||||
const transitionLockRef = useRef(false);
|
const transitionLockRef = useRef(false);
|
||||||
const currentFovRef = useRef(DEFAULT_FOV);
|
const currentFovRef = useRef(DEFAULT_FOV);
|
||||||
const targetFovRef = useRef(DEFAULT_FOV);
|
const targetFovRef = useRef(DEFAULT_FOV);
|
||||||
|
const needsRenderRef = useRef(true);
|
||||||
|
const lastYawRef = useRef(0);
|
||||||
const lastPinchDistanceRef = useRef<number | null>(null);
|
const lastPinchDistanceRef = useRef<number | null>(null);
|
||||||
const infoMarkerRefs = useRef<Map<string, HTMLButtonElement>>(new Map());
|
const infoMarkerRefs = useRef<Map<string, HTMLButtonElement>>(new Map());
|
||||||
const [activeInfoMarker, setActiveInfoMarker] = useState<InfoMarker | null>(null);
|
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("wheel", handleWheel, { passive: false });
|
||||||
renderer.domElement.addEventListener("touchstart", handleTouchStart, { passive: false });
|
renderer.domElement.addEventListener("touchstart", handleTouchStart, { passive: false });
|
||||||
renderer.domElement.addEventListener("touchmove", handleTouchMove, { passive: false });
|
renderer.domElement.addEventListener("touchmove", handleTouchMove, { passive: false });
|
||||||
@@ -1455,8 +1462,9 @@ function TourExperience({
|
|||||||
|
|
||||||
const animate = () => {
|
const animate = () => {
|
||||||
const targetFov = targetFovRef.current;
|
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;
|
currentFovRef.current += (targetFov - currentFovRef.current) * 0.16;
|
||||||
camera.fov = currentFovRef.current;
|
camera.fov = currentFovRef.current;
|
||||||
camera.updateProjectionMatrix();
|
camera.updateProjectionMatrix();
|
||||||
@@ -1464,20 +1472,35 @@ function TourExperience({
|
|||||||
currentFovRef.current = targetFov;
|
currentFovRef.current = targetFov;
|
||||||
camera.fov = targetFov;
|
camera.fov = targetFov;
|
||||||
camera.updateProjectionMatrix();
|
camera.updateProjectionMatrix();
|
||||||
|
needsRenderRef.current = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vrModeRef.current) {
|
// controls.update() trả về true khi camera vừa thay đổi (kể cả damping đang lắng).
|
||||||
controls.update();
|
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();
|
const direction = new THREE.Vector3();
|
||||||
camera.getWorldDirection(direction);
|
camera.getWorldDirection(direction);
|
||||||
const yaw = yawFromDirection(direction);
|
const yaw = yawFromDirection(direction);
|
||||||
|
if (Math.abs(normalizeYaw(yaw - lastYawRef.current)) > 0.15) {
|
||||||
|
lastYawRef.current = yaw;
|
||||||
setCameraYaw(yaw);
|
setCameraYaw(yaw);
|
||||||
|
}
|
||||||
|
|
||||||
updateHotspots();
|
updateHotspots();
|
||||||
|
|
||||||
renderer.render(threeScene, camera);
|
renderer.render(threeScene, camera);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1495,6 +1518,7 @@ function TourExperience({
|
|||||||
renderer.domElement.removeEventListener("pointermove", handlePointerMove);
|
renderer.domElement.removeEventListener("pointermove", handlePointerMove);
|
||||||
renderer.domElement.removeEventListener("pointerup", handlePointerEnd);
|
renderer.domElement.removeEventListener("pointerup", handlePointerEnd);
|
||||||
renderer.domElement.removeEventListener("pointercancel", handlePointerEnd);
|
renderer.domElement.removeEventListener("pointercancel", handlePointerEnd);
|
||||||
|
controls.removeEventListener("change", handleControlsChange);
|
||||||
renderer.setAnimationLoop(null);
|
renderer.setAnimationLoop(null);
|
||||||
controls.dispose();
|
controls.dispose();
|
||||||
geometry.dispose();
|
geometry.dispose();
|
||||||
|
|||||||
Reference in New Issue
Block a user