summaryrefslogtreecommitdiff
path: root/src/core/time-controller.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/time-controller.js')
-rw-r--r--src/core/time-controller.js80
1 files changed, 80 insertions, 0 deletions
diff --git a/src/core/time-controller.js b/src/core/time-controller.js
new file mode 100644
index 0000000..7cd57c7
--- /dev/null
+++ b/src/core/time-controller.js
@@ -0,0 +1,80 @@
+export class TimeController {
+ constructor(store) {
+ this.store = store;
+ this.lastFrameTime = performance.now();
+ }
+
+ tick(now = performance.now()) {
+ const deltaMs = now - this.lastFrameTime;
+ this.lastFrameTime = now;
+
+ this.store.setState((state) => {
+ const realElapsedMs = state.time.realElapsedMs + deltaMs;
+ const plotDeltaMs = state.time.paused ? 0 : deltaMs * state.time.speed;
+
+ return {
+ ...state,
+ time: {
+ ...state.time,
+ realNowMs: Date.now(),
+ realElapsedMs,
+ plotTimeMs: Math.max(0, state.time.plotTimeMs + plotDeltaMs),
+ },
+ };
+ });
+
+ return deltaMs;
+ }
+
+ togglePause() {
+ this.store.setState((state) => ({
+ ...state,
+ time: {
+ ...state.time,
+ paused: !state.time.paused,
+ },
+ }));
+ }
+
+ setPaused(paused) {
+ this.store.setState((state) => ({
+ ...state,
+ time: {
+ ...state.time,
+ paused,
+ },
+ }));
+ }
+
+ setSpeed(speed) {
+ const clampedSpeed = Math.max(0.1, Math.min(12, speed));
+ this.store.setState((state) => ({
+ ...state,
+ time: {
+ ...state.time,
+ speed: clampedSpeed,
+ },
+ }));
+ }
+
+ reset() {
+ this.store.setState((state) => ({
+ ...state,
+ time: {
+ ...state.time,
+ realElapsedMs: 0,
+ plotTimeMs: 0,
+ },
+ plot: {
+ ...state.plot,
+ hoveredPoint: null,
+ tooltip: {
+ ...state.plot.tooltip,
+ visible: false,
+ point: null,
+ },
+ },
+ }));
+ this.lastFrameTime = performance.now();
+ }
+}