Skip to content

Commit 2a49675

Browse files
authored
Merge pull request #93 from Ritika8081/fft-plot
UI Updates for Beta Candle, Bandpower, and FFT Graph
2 parents ad0de19 + 370bf7e commit 2a49675

File tree

4 files changed

+678
-653
lines changed

4 files changed

+678
-653
lines changed

src/components/BandPowerGraph.tsx

Lines changed: 41 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
"use client";
12
import React, {
23
useEffect,
34
useRef,
@@ -122,7 +123,7 @@ const Graph: React.FC<GraphProps> = ({
122123

123124
// Responsive canvas sizing
124125
const containerWidth = container.clientWidth;
125-
const containerHeight = Math.min(containerWidth * 0.5, 400); // Limit max height
126+
const containerHeight = Math.min(containerWidth * 0.5, 400);
126127
canvas.width = containerWidth;
127128
canvas.height = containerHeight;
128129

@@ -131,89 +132,89 @@ const Graph: React.FC<GraphProps> = ({
131132

132133
ctx.clearRect(0, 0, width, height);
133134

134-
// Responsive bar sizing and margins
135-
const leftMargin = width < 500 ? 50 : 70;
135+
// Unified padding and offset to prevent collisions
136+
const padding = Math.min(width, height) * 0.1;
137+
const yAxisLabelOffset = 30;
138+
const topMargin = padding;
139+
const leftMargin = padding + yAxisLabelOffset + 20; // more room for Y-axis label
140+
const bottomMargin = padding + 40; // title + x-axis
141+
const rightMargin = padding;
142+
143+
// Draw axes
144+
const axisColor = theme === "dark" ? "white" : "black";
145+
ctx.beginPath();
146+
ctx.moveTo(leftMargin, topMargin);
147+
ctx.lineTo(leftMargin, height - bottomMargin);
148+
ctx.lineTo(width - rightMargin, height - bottomMargin);
149+
ctx.strokeStyle = axisColor;
150+
ctx.stroke();
136151

137-
const rightMargin = 20;
138-
const bottomMargin = width < 640 ? 40 : 50; // Smaller margin on mobile
139152
const barWidth = (width - leftMargin - rightMargin) / bandNames.length;
140-
const barSpacing = barWidth * 0.2; // Space between bars
153+
const barSpacing = barWidth * 0.3;
141154

142155
let minPower = 0;
143156
let maxPower = 100;
144-
145157
if (maxPower - minPower < 1) {
146158
maxPower = minPower + 1;
147159
}
148160

149-
const axisColor = theme === "dark" ? "white" : "black";
150-
151-
// Draw axes
152-
ctx.beginPath();
153-
ctx.moveTo(leftMargin, 10);
154-
ctx.lineTo(leftMargin, height - bottomMargin);
155-
ctx.lineTo(width - rightMargin, height - bottomMargin);
156-
ctx.strokeStyle = axisColor;
157-
ctx.stroke();
158-
159161
// Draw bars
160-
// Draw bars and beta percentage
161162
currentBandPowerData.forEach((power, index) => {
162163
const x = leftMargin + index * barWidth;
163164
const normalizedHeight = Math.max(0, (power - minPower) / (maxPower - minPower));
164-
const barHeight = Math.max(0, normalizedHeight * (height - bottomMargin - 10));
165-
165+
const barHeight = Math.max(0, normalizedHeight * (height - bottomMargin - topMargin));
166166
const barX = x + barSpacing / 2;
167167
const barY = height - bottomMargin - barHeight;
168-
const actualBarWidth = barWidth - barSpacing * 1.5; // Make it thinner than before
168+
const actualBarWidth = barWidth - barSpacing * 1.5;
169169

170170
ctx.fillStyle = bandColors[index];
171171
ctx.fillRect(barX, barY, actualBarWidth, barHeight);
172-
173-
174172
});
175173

176-
177-
// Draw labels
174+
// Font sizing responsive
175+
const fontSize = width < 640 ? 12 : width < 768 ? 14 : width < 1024 ? 16 : 18;
178176
ctx.fillStyle = axisColor;
179-
const fontSize = width < 640 ? 10 : 12; // Smaller text on mobile
180177
ctx.font = `${fontSize}px Arial`;
181-
182-
// Y-axis labels (log scale)
183178
ctx.textAlign = "right";
184179
ctx.textBaseline = "middle";
185-
const yLabelCount = Math.min(5, Math.floor(height / 50)); // Fewer labels on small screens
180+
181+
const yLabelCount = Math.min(5, Math.floor(height / 50));
186182
for (let i = 0; i <= yLabelCount; i++) {
187183
const value = minPower + (maxPower - minPower) * (i / yLabelCount);
188-
const labelY = height - bottomMargin - (i / yLabelCount) * (height - bottomMargin - 10);
189-
ctx.fillText(value.toFixed(1), leftMargin - 5, labelY);
184+
const labelY = height - bottomMargin - (i / yLabelCount) * (height - bottomMargin - topMargin);
185+
ctx.fillText(value.toFixed(1), leftMargin - 10, labelY);
190186
}
191187

192188
// X-axis labels
193189
ctx.textAlign = "center";
194190
ctx.textBaseline = "top";
195191
bandNames.forEach((band, index) => {
196-
const labelX = leftMargin + index * barWidth + barWidth * 0.5;
192+
const barX = leftMargin + index * barWidth + barSpacing / 2;
193+
const barW = barWidth - barSpacing * 1.5;
194+
const labelX = barX + barW / 2;
197195
ctx.fillText(band, labelX, height - bottomMargin + 5);
198196
});
199197

200-
// EEG Band Power – same as "Frequency (Hz)"
201-
ctx.font = "16px Arial";
198+
// Title: EEG Band Power below graph area with consistent padding
199+
ctx.font = `${fontSize + 2}px Arial`;
202200
ctx.textAlign = "center";
203-
ctx.fillText("EEG Band Power", (width + leftMargin) / 2, height - 17);
201+
ctx.textBaseline = "top";
202+
ctx.fillText("EEG Band Power", width / 2, height - padding + 6);
204203

205-
// Power – same as "Magnitude"
204+
// Y-axis label: Power, fully visible with outer padding
206205
ctx.save();
207206
ctx.rotate(-Math.PI / 2);
208-
ctx.font = "20px Arial";
207+
ctx.font = `${fontSize + 2}px Arial`;
209208
ctx.textAlign = "center";
210-
ctx.fillText("Power", -height / 2, 15);
209+
ctx.textBaseline = "bottom";
210+
ctx.fillText("Power", -height / 2, padding);
211211
ctx.restore();
212-
213212
},
214213
[theme, bandColors, bandNames]
215214
);
216215

216+
217+
217218
// Rest of the component remains the same (animateGraph, useEffect hooks)
218219
const animateGraph = useCallback(() => {
219220
const interpolationFactor = 0.1;
@@ -255,7 +256,7 @@ const Graph: React.FC<GraphProps> = ({
255256
return (
256257
<div
257258
ref={containerRef}
258-
className={`w-full h-full min-h-0 min-w-0 px-4`}
259+
className={`w-full h-full min-h-0 min-w-0 py-2`}
259260
>
260261
<canvas
261262
ref={canvasRef}

0 commit comments

Comments
 (0)