summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--web-timeplot/index.html4
-rw-r--r--web-timeplot/src/main.js73
-rw-r--r--web-timeplot/src/waterfall.js35
3 files changed, 102 insertions, 10 deletions
diff --git a/web-timeplot/index.html b/web-timeplot/index.html
index b93562c..37702a2 100644
--- a/web-timeplot/index.html
+++ b/web-timeplot/index.html
@@ -70,6 +70,8 @@
font-size: 12px;
color: #6f6;
margin-left: auto;
+ min-width: 600px;
+ text-align: right;
}
kbd {
@@ -98,6 +100,8 @@
</div>
<div class="control-group">
<span>Renderer: <span id="renderer-type">Loading...</span></span>
+ <span style="margin-left: 15px;">Time Range Zoom: <span id="time-scale">1.0x</span></span>
+ <span style="font-size: 11px; color: #888;">(Middle-drag ↕)</span>
</div>
<div class="info" id="metrics-display">
Starting...
diff --git a/web-timeplot/src/main.js b/web-timeplot/src/main.js
index abcd72f..b0ba032 100644
--- a/web-timeplot/src/main.js
+++ b/web-timeplot/src/main.js
@@ -24,6 +24,13 @@ let app = null; // PixiJS Application
let graphs = [];
let metrics = null;
let time = 0;
+let frameCounter = 0;
+let metricsUpdateInterval = 10; // Update metrics display every N frames
+
+// Vertical zoom dragging state
+let isDraggingVerticalZoom = false;
+let dragStartY = 0;
+let dragStartZoom = 1.0;
// ============================================================================
// APPLICATION ENTRY POINT
@@ -64,6 +71,7 @@ async function initDOM() {
dom.controls.exportBtn = document.getElementById('export-metrics');
dom.display.rendererType = document.getElementById('renderer-type');
dom.display.metrics = document.getElementById('metrics-display');
+ dom.display.timeScale = document.getElementById('time-scale');
}
async function initCfg() {
@@ -90,8 +98,6 @@ async function initRenderer() {
log('WebGPU not available, using WebGL');
preference = 'webgl';
}
- console.log(navigator.gpu);
- console.log(navigator);
try {
app = new Application();
@@ -172,6 +178,12 @@ function setupControls() {
// Keyboard controls
window.addEventListener('keydown', handleKeyboard);
+ // Mouse controls for time scaling
+ dom.container.addEventListener('mousedown', handleMouseDown);
+ window.addEventListener('mousemove', handleMouseMove);
+ window.addEventListener('mouseup', handleMouseUp);
+ dom.container.addEventListener('contextmenu', (e) => e.preventDefault()); // Prevent context menu
+
// Update button states
updateControlButtons();
}
@@ -205,6 +217,40 @@ function handleResize() {
if (graphs[1]) graphs[1].resize(width / 2, 0, width / 2, height);
}
+function handleMouseDown(e) {
+ // Middle mouse button (button = 1)
+ if (e.button === 1) {
+ e.preventDefault();
+ isDraggingVerticalZoom = true;
+ dragStartY = e.clientY;
+ dragStartZoom = graphs[0]?.getVerticalScale() || 1.0;
+ dom.container.style.cursor = 'ns-resize';
+ }
+}
+
+function handleMouseMove(e) {
+ if (!isDraggingVerticalZoom) return;
+
+ const deltaY = dragStartY - e.clientY; // Inverted: drag up = zoom in
+ const sensitivity = 0.005; // Adjust sensitivity
+ const newZoom = dragStartZoom + (deltaY * sensitivity);
+
+ // Apply to all graphs
+ graphs.forEach(graph => {
+ graph.setVerticalScale(newZoom);
+ });
+
+ // Update display
+ updateVerticalZoomDisplay();
+}
+
+function handleMouseUp(e) {
+ if (e.button === 1) {
+ isDraggingVerticalZoom = false;
+ dom.container.style.cursor = 'default';
+ }
+}
+
// ============================================================================
// MAIN UPDATE LOOP
// ============================================================================
@@ -214,6 +260,7 @@ function update() {
metrics.beginUpdate();
time += 0.016; // ~60fps increment
+ frameCounter++;
// Update each graph
graphs.forEach((graph, idx) => {
@@ -232,12 +279,10 @@ function update() {
metrics.endFrame(updateMs, renderMs, vertexCount, lineCount);
- // Update UI
- if (cfg.showMetrics) {
+ // Update UI less frequently to prevent flickering
+ if (cfg.showMetrics && frameCounter % metricsUpdateInterval === 0) {
updateMetricsDisplay();
}
-
- console.log(metrics);
}
// ============================================================================
@@ -282,6 +327,22 @@ function updateControlButtons() {
dom.controls.metricsBtn.classList.toggle('active', cfg.showMetrics);
}
+function updateVerticalZoomDisplay() {
+ if (dom.display.timeScale && graphs[0]) {
+ const zoom = graphs[0].getVerticalScale();
+ dom.display.timeScale.textContent = `${zoom.toFixed(2)}x`;
+
+ // Color code: zoomed out = blue, normal = white, zoomed in = orange
+ if (zoom < 0.8) {
+ dom.display.timeScale.style.color = '#6af'; // Zoomed out (see more history)
+ } else if (zoom > 1.2) {
+ dom.display.timeScale.style.color = '#fa6'; // Zoomed in (see less history)
+ } else {
+ dom.display.timeScale.style.color = '#fff';
+ }
+ }
+}
+
// ============================================================================
// UTILITIES
// ============================================================================
diff --git a/web-timeplot/src/waterfall.js b/web-timeplot/src/waterfall.js
index 78d8e40..bce0750 100644
--- a/web-timeplot/src/waterfall.js
+++ b/web-timeplot/src/waterfall.js
@@ -47,6 +47,11 @@ export class WaterfallGraph {
this.showGrid = true;
+ // Time scaling and zoom
+ this.scrollSpeed = 1.0; // Speed multiplier for scrolling
+ this.baseScrollSpeed = 1.0;
+ this.verticalScale = 1.0; // Vertical zoom: >1 = zoomed in (see less history), <1 = zoomed out (see more)
+
this.draw();
}
@@ -129,26 +134,48 @@ export class WaterfallGraph {
}
scrollLines() {
- const scrollSpeed = 1.0;
+ const speed = this.baseScrollSpeed * this.scrollSpeed;
this.lines.forEach(line => {
- line.yOffset += scrollSpeed;
+ line.yOffset += speed;
});
}
+ setScrollSpeed(speed) {
+ // Clamp between 0.1 (slow) and 5.0 (fast)
+ this.scrollSpeed = Math.max(0.1, Math.min(5.0, speed));
+ }
+
+ getScrollSpeed() {
+ return this.scrollSpeed;
+ }
+
+ setVerticalScale(scale) {
+ // Clamp between 0.2 (zoomed out, see more history) and 3.0 (zoomed in, see less)
+ this.verticalScale = Math.max(0.2, Math.min(3.0, scale));
+ }
+
+ getVerticalScale() {
+ return this.verticalScale;
+ }
+
drawLines() {
this.linesGraphics.clear();
for (const line of this.lines) {
if (line.points.length < 2) continue;
+ // Apply vertical scale to y positions
+ // Current time is at top (y=0), older data has larger yOffset
+ const scaledYOffset = line.yOffset * this.verticalScale;
+
// Start path
const firstPoint = line.points[0];
- this.linesGraphics.moveTo(firstPoint.x, firstPoint.y + line.yOffset);
+ this.linesGraphics.moveTo(firstPoint.x, firstPoint.y + scaledYOffset);
// Draw line strip
for (let i = 1; i < line.points.length; i++) {
const point = line.points[i];
- this.linesGraphics.lineTo(point.x, point.y + line.yOffset);
+ this.linesGraphics.lineTo(point.x, point.y + scaledYOffset);
}
this.linesGraphics.stroke({ width: 2, color: line.color });