File size: 1,891 Bytes
ca28016
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import React, { useRef, useEffect } from "react";

interface NeonOscilloscopeProps {
  data: number[];
  width?: number;
  height?: number;
}

export default function NeonOscilloscope({ data, width = 600, height = 200 }: NeonOscilloscopeProps) {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    if (!ctx) return;
    ctx.clearRect(0, 0, width, height);
    // Neon grid
    ctx.save();
    ctx.globalAlpha = 0.18;
    ctx.strokeStyle = "#00ffe7";
    ctx.lineWidth = 1;
    for (let x = 0; x < width; x += 40) {
      ctx.beginPath();
      ctx.moveTo(x, 0);
      ctx.lineTo(x, height);
      ctx.stroke();
    }
    for (let y = 0; y < height; y += 40) {
      ctx.beginPath();
      ctx.moveTo(0, y);
      ctx.lineTo(width, y);
      ctx.stroke();
    }
    ctx.restore();
    // Neon trace
    ctx.save();
    ctx.shadowColor = "#00ffe7";
    ctx.shadowBlur = 16;
    ctx.strokeStyle = "#00ffe7";
    ctx.lineWidth = 2.5;
    ctx.beginPath();
    data.forEach((v, i) => {
      const x = (i / (data.length - 1)) * width;
      const y = height / 2 - v * (height / 2 - 10);
      if (i === 0) ctx.moveTo(x, y);
      else ctx.lineTo(x, y);
    });
    ctx.stroke();
    ctx.restore();
  }, [data, width, height]);
  return (
    <div style={{ position: "relative", width, height }}>
      <canvas ref={canvasRef} width={width} height={height} style={{ display: "block", width, height, background: "#10131a", borderRadius: 12, boxShadow: "0 0 24px #00ffe7" }} />
      <div className="neon-grid" style={{ width, height, position: "absolute", left: 0, top: 0 }} />
      <div style={{ position: "absolute", right: 16, top: 16, zIndex: 2 }}>
        <span className="segment-readout">{data[data.length - 1]?.toFixed(3)}</span>
      </div>
    </div>
  );
}