summaryrefslogtreecommitdiff
path: root/web-timeplot/src/timeseries-plot.js
diff options
context:
space:
mode:
Diffstat (limited to 'web-timeplot/src/timeseries-plot.js')
-rw-r--r--web-timeplot/src/timeseries-plot.js277
1 files changed, 0 insertions, 277 deletions
diff --git a/web-timeplot/src/timeseries-plot.js b/web-timeplot/src/timeseries-plot.js
deleted file mode 100644
index e35a704..0000000
--- a/web-timeplot/src/timeseries-plot.js
+++ /dev/null
@@ -1,277 +0,0 @@
-import { Container, Graphics, Text } from 'pixi.js';
-
-/**
- * TimeSeriesPlot - Pure visualization component for time-series data
- *
- * This class is responsible ONLY for displaying data, not generating it.
- * It receives data points from external sources and renders them as a
- * scrolling waterfall display.
- *
- * Architecture:
- * - TimeSeriesPlot: Displays data (this file)
- * - DataSource: Generates/provides data (data-sources.js)
- * - Connection: Links sources to plots
- */
-export class TimeSeriesPlot {
- constructor(config) {
- this.x = config.x || 0;
- this.y = config.y || 0;
- this.width = config.width || 800;
- this.height = config.height || 600;
- this.title = config.title || 'Time Series';
- this.baseColor = config.color || 0xff6666;
-
- // Container for all graphics
- this.container = new Container();
- this.container.x = this.x;
- this.container.y = this.y;
-
- // Graphics layers (order matters for rendering)
- this.gridGraphics = new Graphics();
- this.linesGraphics = new Graphics();
- this.borderGraphics = new Graphics();
-
- this.container.addChild(this.gridGraphics);
- this.container.addChild(this.linesGraphics);
- this.container.addChild(this.borderGraphics);
-
- // Title
- this.titleText = new Text({
- text: this.title,
- style: {
- fontFamily: 'Arial',
- fontSize: 18,
- fill: 0xeeeeee,
- }
- });
- this.titleText.x = 10;
- this.titleText.y = 10;
- this.container.addChild(this.titleText);
-
- // Display state
- this.lines = []; // Array of {points, yOffset, color, metadata}
- this.maxLines = config.maxLines || 100;
- this.showGrid = config.showGrid !== false;
-
- // Scrolling and scaling
- this.scrollSpeed = config.scrollSpeed || 1.0;
- this.verticalScale = config.verticalScale || 1.0;
-
- // Initial draw
- this.draw();
- }
-
- // ========================================================================
- // Data Input API - This is how external sources send data to the plot
- // ========================================================================
-
- /**
- * Add a new line of data to the plot
- * @param {Array<{x: number, y: number}>} points - Array of points
- * @param {Object} metadata - Optional metadata (color, timestamp, etc.)
- */
- addLine(points, metadata = {}) {
- const line = {
- points: points,
- yOffset: 0,
- color: metadata.color || this.generateColor(Date.now() / 1000),
- timestamp: metadata.timestamp || Date.now(),
- metadata: metadata,
- };
-
- this.lines.push(line);
-
- // Limit number of lines
- if (this.lines.length > this.maxLines) {
- this.lines.shift();
- }
- }
-
- /**
- * Add a single data point (will be buffered into a line)
- * This is useful for streaming real-time data
- * @param {number} timestamp - Time of the data point
- * @param {number} value - Value at this time
- */
- addDataPoint(timestamp, value) {
- // For now, this creates a single-point line
- // In a more sophisticated version, this could buffer points
- // until a full line is ready
- const point = { x: this.width / 2, y: value };
- this.addLine([point], { timestamp });
- }
-
- /**
- * Clear all data from the plot
- */
- clearData() {
- this.lines = [];
- this.drawLines();
- }
-
- // ========================================================================
- // Update and Rendering
- // ========================================================================
-
- /**
- * Update the plot - called each frame
- * This handles scrolling and cleanup, but NOT data generation
- */
- update() {
- // Scroll existing lines down
- this.scrollLines();
-
- // Remove off-screen lines
- this.lines = this.lines.filter(line => {
- const scaledOffset = line.yOffset * this.verticalScale;
- return scaledOffset < this.height + 50;
- });
-
- // Redraw
- this.drawLines();
- }
-
- scrollLines() {
- this.lines.forEach(line => {
- line.yOffset += this.scrollSpeed;
- });
- }
-
- draw() {
- this.drawBorder();
- this.drawGrid();
- this.drawLines();
- }
-
- drawBorder() {
- this.borderGraphics.clear();
- this.borderGraphics.rect(0, 0, this.width, this.height);
- this.borderGraphics.stroke({ width: 2, color: 0x606070 });
- }
-
- drawGrid() {
- this.gridGraphics.clear();
-
- if (!this.showGrid) return;
-
- this.gridGraphics.alpha = 0.3;
-
- const divisions = 10;
- const color = 0x4a7a9a;
-
- // Vertical lines
- for (let i = 0; i <= divisions; i++) {
- const x = (i / divisions) * this.width;
- this.gridGraphics.moveTo(x, 0);
- this.gridGraphics.lineTo(x, this.height);
- this.gridGraphics.stroke({ width: 1, color });
- }
-
- // Horizontal lines
- for (let i = 0; i <= divisions; i++) {
- const y = (i / divisions) * this.height;
- this.gridGraphics.moveTo(0, y);
- this.gridGraphics.lineTo(this.width, y);
- this.gridGraphics.stroke({ width: 1, color });
- }
- }
-
- drawLines() {
- this.linesGraphics.clear();
-
- for (const line of this.lines) {
- if (line.points.length < 2) continue;
-
- // Apply vertical scale to y positions
- const scaledYOffset = line.yOffset * this.verticalScale;
-
- // Start path
- const firstPoint = line.points[0];
- 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 + scaledYOffset);
- }
-
- this.linesGraphics.stroke({ width: 2, color: line.color });
- }
- }
-
- generateColor(time) {
- // Cycle through colors based on time
- const hue = (time * 0.1) % 1.0;
- const r = Math.floor(Math.abs(Math.sin(hue * Math.PI * 2)) * 255);
- const g = Math.floor(Math.abs(Math.sin((hue + 0.33) * Math.PI * 2)) * 255);
- const b = Math.floor(Math.abs(Math.sin((hue + 0.66) * Math.PI * 2)) * 255);
-
- return (r << 16) | (g << 8) | b;
- }
-
- // ========================================================================
- // Configuration and Control
- // ========================================================================
-
- setGridVisible(visible) {
- this.showGrid = visible;
- this.drawGrid();
- }
-
- setScrollSpeed(speed) {
- this.scrollSpeed = Math.max(0.1, Math.min(10.0, speed));
- }
-
- setVerticalScale(scale) {
- this.verticalScale = Math.max(0.2, Math.min(3.0, scale));
- }
-
- setTitle(title) {
- this.title = title;
- this.titleText.text = title;
- }
-
- resize(x, y, width, height) {
- this.x = x;
- this.y = y;
- this.width = width;
- this.height = height;
-
- this.container.x = x;
- this.container.y = y;
-
- this.draw();
- }
-
- // ========================================================================
- // Statistics and Debugging
- // ========================================================================
-
- getVertexCount() {
- return this.lines.reduce((sum, line) => sum + line.points.length, 0);
- }
-
- getLineCount() {
- return this.lines.length;
- }
-
- getOldestTimestamp() {
- if (this.lines.length === 0) return null;
- return Math.min(...this.lines.map(l => l.timestamp));
- }
-
- getNewestTimestamp() {
- if (this.lines.length === 0) return null;
- return Math.max(...this.lines.map(l => l.timestamp));
- }
-
- getStats() {
- return {
- lineCount: this.getLineCount(),
- vertexCount: this.getVertexCount(),
- oldestTimestamp: this.getOldestTimestamp(),
- newestTimestamp: this.getNewestTimestamp(),
- timeSpan: this.getNewestTimestamp() - this.getOldestTimestamp(),
- };
- }
-}