@@ -112,32 +112,34 @@ const Graph: React.FC<GraphProps> = ({
112112 const canvas = canvasRef . current ;
113113 const container = containerRef . current ;
114114 if ( ! canvas || ! container ) return ;
115-
115+
116116 if ( currentBandPowerData . some ( isNaN ) ) {
117117 console . error ( "NaN values detected in band power data" ) ;
118118 return ;
119119 }
120-
120+
121121 const ctx = canvas . getContext ( "2d" ) ;
122122 if ( ! ctx ) return ;
123-
123+
124124 // Responsive canvas sizing
125125 const containerWidth = container . clientWidth ;
126- const containerHeight = Math . min ( containerWidth * 0.5 , 400 ) ; // Limit max height
126+ const containerHeight = Math . min ( containerWidth * 0.5 , 400 ) ;
127127 canvas . width = containerWidth ;
128128 canvas . height = containerHeight ;
129-
129+
130130 const width = canvas . width ;
131131 const height = canvas . height ;
132-
132+
133133 ctx . clearRect ( 0 , 0 , width , height ) ;
134-
135- // inside drawGraph:
136- const topMargin = 30 ; // space for any in-canvas labels
137- const leftMargin = width < 500 ? 50 : 60 ;
138- const bottomMargin = width < 640 ? 40 : 50 ;
139- const rightMargin = 20 ;
140-
134+
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+
141143 // Draw axes
142144 const axisColor = theme === "dark" ? "white" : "black" ;
143145 ctx . beginPath ( ) ;
@@ -146,44 +148,44 @@ const Graph: React.FC<GraphProps> = ({
146148 ctx . lineTo ( width - rightMargin , height - bottomMargin ) ;
147149 ctx . strokeStyle = axisColor ;
148150 ctx . stroke ( ) ;
149-
151+
150152 const barWidth = ( width - leftMargin - rightMargin ) / bandNames . length ;
151- const barSpacing = barWidth * 0.3 ; // Space between bars
152-
153+ const barSpacing = barWidth * 0.3 ;
154+
153155 let minPower = 0 ;
154156 let maxPower = 100 ;
155157 if ( maxPower - minPower < 1 ) {
156158 maxPower = minPower + 1 ;
157159 }
158-
160+
159161 // Draw bars
160162 currentBandPowerData . forEach ( ( power , index ) => {
161163 const x = leftMargin + index * barWidth ;
162164 const normalizedHeight = Math . max ( 0 , ( power - minPower ) / ( maxPower - minPower ) ) ;
163165 const barHeight = Math . max ( 0 , normalizedHeight * ( height - bottomMargin - topMargin ) ) ;
164-
165166 const barX = x + barSpacing / 2 ;
166167 const barY = height - bottomMargin - barHeight ;
167- const actualBarWidth = barWidth - barSpacing * 1.5 ; // Make it thinner than before
168-
168+ const actualBarWidth = barWidth - barSpacing * 1.5 ;
169+
169170 ctx . fillStyle = bandColors [ index ] ;
170171 ctx . fillRect ( barX , barY , actualBarWidth , barHeight ) ;
171172 } ) ;
172-
173- // Y-axis labels
173+
174+ // Font sizing responsive
175+ const fontSize = width < 640 ? 12 : width < 768 ? 14 : width < 1024 ? 16 : 18 ;
174176 ctx . fillStyle = axisColor ;
175- const fontSize = width < 640 ? 10 : 12 ; // Smaller text on mobile
176177 ctx . font = `${ fontSize } px Arial` ;
177178 ctx . textAlign = "right" ;
178179 ctx . textBaseline = "middle" ;
180+
179181 const yLabelCount = Math . min ( 5 , Math . floor ( height / 50 ) ) ;
180182 for ( let i = 0 ; i <= yLabelCount ; i ++ ) {
181183 const value = minPower + ( maxPower - minPower ) * ( i / yLabelCount ) ;
182184 const labelY = height - bottomMargin - ( i / yLabelCount ) * ( height - bottomMargin - topMargin ) ;
183- ctx . fillText ( value . toFixed ( 1 ) , leftMargin - 5 , labelY ) ;
185+ ctx . fillText ( value . toFixed ( 1 ) , leftMargin - 10 , labelY ) ;
184186 }
185-
186- // X-axis labels, centered under each actual bar
187+
188+ // X-axis labels
187189 ctx . textAlign = "center" ;
188190 ctx . textBaseline = "top" ;
189191 bandNames . forEach ( ( band , index ) => {
@@ -192,23 +194,26 @@ const Graph: React.FC<GraphProps> = ({
192194 const labelX = barX + barW / 2 ;
193195 ctx . fillText ( band , labelX , height - bottomMargin + 5 ) ;
194196 } ) ;
195-
196- // Title
197- ctx . font = "1.2em Arial" ;
197+
198+ // Title: EEG Band Power below graph area with consistent padding
199+ ctx . font = ` ${ fontSize + 2 } px Arial` ;
198200 ctx . textAlign = "center" ;
199- ctx . fillText ( "EEG Band Power" , ( width + leftMargin ) / 2 , height - 17 ) ;
200-
201- // Power (Y-axis name) inside canvas
201+ ctx . textBaseline = "top" ;
202+ ctx . fillText ( "EEG Band Power" , width / 2 , height - padding + 6 ) ;
203+
204+ // Y-axis label: Power, fully visible with outer padding
202205 ctx . save ( ) ;
203206 ctx . rotate ( - Math . PI / 2 ) ;
204- ctx . font = "1.2em Arial" ;
207+ ctx . font = ` ${ fontSize + 2 } px Arial` ;
205208 ctx . textAlign = "center" ;
206- ctx . fillText ( "Power" , - height / 2 , 15 ) ;
209+ ctx . textBaseline = "bottom" ;
210+ ctx . fillText ( "Power" , - height / 2 , padding ) ;
207211 ctx . restore ( ) ;
208212 } ,
209213 [ theme , bandColors , bandNames ]
210214 ) ;
211-
215+
216+
212217
213218 // Rest of the component remains the same (animateGraph, useEffect hooks)
214219 const animateGraph = useCallback ( ( ) => {
0 commit comments