diff options
| author | grothedev <grothedev@gmail.com> | 2025-10-02 20:13:46 -0400 |
|---|---|---|
| committer | grothedev <grothedev@gmail.com> | 2025-10-02 20:13:46 -0400 |
| commit | 39124e6854b2740e9f30c058e873355dfd739a4e (patch) | |
| tree | 5cd1fb7986b1aebbde79ce478ecfc0b077690414 /web-timeplot/src/waterfall.js | |
| parent | 836459dce3f50767d41978be4a2f7ac788e6a9ba (diff) | |
starting with pixijs implementation
Diffstat (limited to 'web-timeplot/src/waterfall.js')
| -rw-r--r-- | web-timeplot/src/waterfall.js | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/web-timeplot/src/waterfall.js b/web-timeplot/src/waterfall.js new file mode 100644 index 0000000..78d8e40 --- /dev/null +++ b/web-timeplot/src/waterfall.js @@ -0,0 +1,192 @@ +import { Container, Graphics, Text } from 'pixi.js'; + +/** + * WaterfallGraph - A scrolling waterfall display + * Starts simple with basic line rendering + */ +export class WaterfallGraph { + constructor(config) { + this.x = config.x; + this.y = config.y; + this.width = config.width; + this.height = config.height; + this.title = config.title; + this.baseColor = config.color || 0xff6666; + + this.container = new Container(); + this.container.x = this.x; + this.container.y = this.y; + + // Graphics layers + this.borderGraphics = new Graphics(); + this.gridGraphics = new Graphics(); + this.linesGraphics = new Graphics(); + + this.container.addChild(this.gridGraphics); + this.container.addChild(this.linesGraphics); + this.container.addChild(this.borderGraphics); + + // Title text + 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); + + // Waterfall data + this.lines = []; + this.maxLines = 50; + this.pointsPerLine = 100; + this.frameCounter = 0; + + this.showGrid = true; + + this.draw(); + } + + draw() { + this.drawBorder(); + this.drawGrid(); + } + + 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 }); + } + } + + update(time, graphIdx) { + this.frameCounter++; + + // Add new line every 10 frames + if (this.frameCounter % 10 === 0 && this.lines.length < this.maxLines) { + this.addLine(time, graphIdx); + } + + // Scroll existing lines down + this.scrollLines(); + + // Remove off-screen lines + this.lines = this.lines.filter(line => line.yOffset < this.height + 50); + + // Redraw all lines + this.drawLines(); + } + + addLine(time, graphIdx) { + const line = { + points: [], + yOffset: 0, + color: this.generateColor(time), + }; + + // Generate sine wave points + const phase = time + (graphIdx * 2); + const freq = 2.0 + Math.sin(time * 0.5 + graphIdx) * 1.0; + + for (let i = 0; i < this.pointsPerLine; i++) { + const x = (i / this.pointsPerLine) * this.width; + const normalizedX = (i / this.pointsPerLine) * 2 - 1; // -1 to 1 + const y = Math.sin(i * 0.1 * freq + phase) * 30; // Amplitude in pixels + + line.points.push({ x, y }); + } + + this.lines.push(line); + } + + scrollLines() { + const scrollSpeed = 1.0; + this.lines.forEach(line => { + line.yOffset += scrollSpeed; + }); + } + + drawLines() { + this.linesGraphics.clear(); + + for (const line of this.lines) { + if (line.points.length < 2) continue; + + // Start path + const firstPoint = line.points[0]; + this.linesGraphics.moveTo(firstPoint.x, firstPoint.y + line.yOffset); + + // 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.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; + } + + setGridVisible(visible) { + this.showGrid = visible; + this.drawGrid(); + } + + 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(); + } + + getVertexCount() { + return this.lines.reduce((sum, line) => sum + line.points.length, 0); + } + + getLineCount() { + return this.lines.length; + } +} |
