@@ -45,13 +45,23 @@ class InteractiveChart extends StatefulWidget {
4545 /// ```
4646 final OverlayInfoGetter ? overlayInfo;
4747
48+ /// An optional event, fired when the user clicks on a candlestick.
49+ final ValueChanged <CandleData >? onTap;
50+
51+ /// An optional event, fired when user zooms in/out.
52+ ///
53+ /// This provides the width of a candlestick at the current zoom level.
54+ final ValueChanged <double >? onCandleResize;
55+
4856 const InteractiveChart ({
4957 Key ? key,
5058 required this .candles,
5159 ChartStyle ? style,
5260 this .timeLabel,
5361 this .priceLabel,
5462 this .overlayInfo,
63+ this .onTap,
64+ this .onCandleResize,
5565 }) : this .style = style ?? const ChartStyle (),
5666 assert (candles.length >= 3 ,
5767 "InteractiveChart requires 3 or more CandleData" ),
@@ -78,6 +88,7 @@ class _InteractiveChartState extends State<InteractiveChart> {
7888 late double _prevCandleWidth;
7989 late double _prevStartOffset;
8090 late Offset _initialFocalPoint;
91+ PainterParams ? _prevParams; // used in onTapUp event
8192
8293 @override
8394 Widget build (BuildContext context) {
@@ -140,7 +151,13 @@ class _InteractiveChartState extends State<InteractiveChart> {
140151 setState (() => _tapPosition = details.localPosition);
141152 },
142153 onTapCancel: () => setState (() => _tapPosition = null ),
143- onTapUp: (_) => setState (() => _tapPosition = null ),
154+ onTapUp: (_) {
155+ if (widget.onTap != null ) {
156+ _fireOnTapEvent (); // Fire callback event (if needed)
157+ }
158+ setState (() => _tapPosition = null );
159+ },
160+
144161 // Pan and zoom
145162 onScaleStart: (details) {
146163 _prevCandleWidth = _candleWidth;
@@ -166,10 +183,10 @@ class _InteractiveChartState extends State<InteractiveChart> {
166183 trailingTrend: trailingTrend,
167184 ),
168185 ),
169- // duration: Duration.zero,
170186 duration: Duration (milliseconds: 300 ),
171187 curve: Curves .easeOut,
172188 builder: (_, PainterParams params, __) {
189+ _prevParams = params;
173190 return RepaintBoundary (
174191 child: CustomPaint (
175192 size: size,
@@ -204,6 +221,10 @@ class _InteractiveChartState extends State<InteractiveChart> {
204221 final focalPointFactor = details.localFocalPoint.dx / w;
205222 startOffset -= zoomAdjustment * focalPointFactor;
206223 startOffset = startOffset.clamp (0 , _getMaxStartOffset (w, candleWidth));
224+ // Fire candle width resize event
225+ if (candleWidth != _candleWidth) {
226+ widget.onCandleResize? .call (candleWidth);
227+ }
207228 // Apply changes
208229 setState (() {
209230 _candleWidth = candleWidth;
@@ -276,6 +297,15 @@ class _InteractiveChartState extends State<InteractiveChart> {
276297 "Volume" : candle.volume? .asAbbreviated () ?? "-" ,
277298 };
278299 }
300+
301+ void _fireOnTapEvent () {
302+ if (_prevParams == null || _tapPosition == null ) return ;
303+ final params = _prevParams! ;
304+ final dx = _tapPosition! .dx;
305+ final selected = params.getCandleIndexFromOffset (dx);
306+ final candle = params.candles[selected];
307+ widget.onTap? .call (candle);
308+ }
279309}
280310
281311extension Formatting on double {
0 commit comments