fix: pause animation loop while not rendering
This commit is contained in:
@@ -192,6 +192,7 @@ let mesh = null;
|
|||||||
let directionalLight = null;
|
let directionalLight = null;
|
||||||
let ambientLight = null;
|
let ambientLight = null;
|
||||||
let animationId = null;
|
let animationId = null;
|
||||||
|
let animationPaused = false;
|
||||||
|
|
||||||
// Geometry cache for height exaggeration
|
// Geometry cache for height exaggeration
|
||||||
let geometryCache = null;
|
let geometryCache = null;
|
||||||
@@ -233,8 +234,19 @@ const initThreeJS = () => {
|
|||||||
|
|
||||||
updateLightPosition();
|
updateLightPosition();
|
||||||
|
|
||||||
// Animation loop
|
// Don't start animation loop yet - will be controlled by pause/resume
|
||||||
|
};
|
||||||
|
|
||||||
|
// Animation loop control
|
||||||
|
const startAnimation = () => {
|
||||||
|
if (animationId) return; // Already running
|
||||||
|
|
||||||
const animate = () => {
|
const animate = () => {
|
||||||
|
if (animationPaused) {
|
||||||
|
animationId = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
animationId = requestAnimationFrame(animate);
|
animationId = requestAnimationFrame(animate);
|
||||||
if (renderer && scene && camera) {
|
if (renderer && scene && camera) {
|
||||||
renderer.render(scene, camera);
|
renderer.render(scene, camera);
|
||||||
@@ -243,6 +255,26 @@ const initThreeJS = () => {
|
|||||||
animate();
|
animate();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const pauseAnimation = () => {
|
||||||
|
animationPaused = true;
|
||||||
|
if (animationId) {
|
||||||
|
cancelAnimationFrame(animationId);
|
||||||
|
animationId = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const resumeAnimation = () => {
|
||||||
|
animationPaused = false;
|
||||||
|
startAnimation();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Render a single frame (for when animation is paused but we need to update the view)
|
||||||
|
const renderSingleFrame = () => {
|
||||||
|
if (renderer && scene && camera) {
|
||||||
|
renderer.render(scene, camera);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Handle canvas resize
|
// Handle canvas resize
|
||||||
const handleResize = () => {
|
const handleResize = () => {
|
||||||
if (!canvasRef.value || !renderer || !camera) return;
|
if (!canvasRef.value || !renderer || !camera) return;
|
||||||
@@ -422,11 +454,13 @@ const updateHeightScale = () => {
|
|||||||
|
|
||||||
geometryCache.geometry.attributes.position.needsUpdate = true;
|
geometryCache.geometry.attributes.position.needsUpdate = true;
|
||||||
geometryCache.geometry.computeVertexNormals();
|
geometryCache.geometry.computeVertexNormals();
|
||||||
|
renderSingleFrame(); // Render once to show the change
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update scene (for real-time preview)
|
// Update scene (for real-time preview)
|
||||||
const updateScene = () => {
|
const updateScene = () => {
|
||||||
updateLightPosition();
|
updateLightPosition();
|
||||||
|
renderSingleFrame(); // Render once to show the change
|
||||||
};
|
};
|
||||||
|
|
||||||
// Color conversion utilities
|
// Color conversion utilities
|
||||||
@@ -438,6 +472,7 @@ const updateColor = (e) => {
|
|||||||
settings.terrainColor = parseInt(e.target.value.replace('#', ''), 16);
|
settings.terrainColor = parseInt(e.target.value.replace('#', ''), 16);
|
||||||
if (mesh && mesh.material) {
|
if (mesh && mesh.material) {
|
||||||
mesh.material.color.setHex(settings.terrainColor);
|
mesh.material.color.setHex(settings.terrainColor);
|
||||||
|
renderSingleFrame(); // Render once to show the change
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -634,9 +669,7 @@ const downloadLastRender = () => {
|
|||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
const cleanup = () => {
|
const cleanup = () => {
|
||||||
if (animationId) {
|
pauseAnimation();
|
||||||
cancelAnimationFrame(animationId);
|
|
||||||
}
|
|
||||||
if (resizeObserver) {
|
if (resizeObserver) {
|
||||||
resizeObserver.disconnect();
|
resizeObserver.disconnect();
|
||||||
resizeObserver = null;
|
resizeObserver = null;
|
||||||
@@ -663,6 +696,11 @@ onMounted(() => {
|
|||||||
});
|
});
|
||||||
resizeObserver.observe(canvasRef.value);
|
resizeObserver.observe(canvasRef.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only start animation if visible and not offscreen
|
||||||
|
if (!props.offscreen) {
|
||||||
|
resumeAnimation();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -680,7 +718,29 @@ watch(() => props.visible, (newVal) => {
|
|||||||
});
|
});
|
||||||
resizeObserver.observe(canvasRef.value);
|
resizeObserver.observe(canvasRef.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start animation when visible and not offscreen
|
||||||
|
if (!props.offscreen) {
|
||||||
|
resumeAnimation();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
} else if (newVal && !props.offscreen) {
|
||||||
|
// Component already initialized, just resume animation
|
||||||
|
resumeAnimation();
|
||||||
|
} else if (!newVal) {
|
||||||
|
// Hidden - pause animation
|
||||||
|
pauseAnimation();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Watch for offscreen changes
|
||||||
|
watch(() => props.offscreen, (newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
// Offscreen mode - pause animation (we only render single frames on demand)
|
||||||
|
pauseAnimation();
|
||||||
|
} else if (props.visible) {
|
||||||
|
// Not offscreen and visible - resume animation
|
||||||
|
resumeAnimation();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -721,8 +781,7 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
|
|
||||||
.modal-container.offscreen {
|
.modal-container.offscreen {
|
||||||
left: -10000px;
|
display: none;
|
||||||
top: -10000px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-header {
|
.modal-header {
|
||||||
|
|||||||
Reference in New Issue
Block a user