@@ -80,11 +80,16 @@ class _ChartState extends State<Chart> with TickerProviderStateMixin {
80
80
AnimationController _loadingAnimationController;
81
81
AnimationController _topBoundQuoteAnimationController;
82
82
AnimationController _bottomBoundQuoteAnimationController;
83
+ AnimationController _rightEpochAnimationController;
83
84
Animation _currentTickAnimation;
84
85
Animation _currentTickBlinkAnimation;
85
86
86
87
bool get _shouldAutoPan => rightBoundEpoch > nowEpoch;
87
88
89
+ bool get _arrowButtonBeVisible =>
90
+ ! _shouldAutoPan &&
91
+ ! (_rightEpochAnimationController? .isAnimating ?? false );
92
+
88
93
double get _topBoundQuote => _topBoundQuoteAnimationController.value;
89
94
90
95
double get _bottomBoundQuote => _bottomBoundQuoteAnimationController.value;
@@ -129,19 +134,20 @@ class _ChartState extends State<Chart> with TickerProviderStateMixin {
129
134
130
135
if (oldGranularity != newGranularity) {
131
136
msPerPx = _getDefaultScale (newGranularity);
132
- _scrollToNow ( );
137
+ rightBoundEpoch = nowEpoch + _pxToMs (maxCurrentTickOffset );
133
138
} else {
134
139
_onNewTick ();
135
140
}
136
141
}
137
142
138
143
@override
139
144
void dispose () {
140
- _currentTickAnimationController.dispose ();
141
- _currentTickBlinkingController.dispose ();
142
- _loadingAnimationController.dispose ();
143
- _topBoundQuoteAnimationController.dispose ();
144
- _bottomBoundQuoteAnimationController.dispose ();
145
+ _rightEpochAnimationController? .dispose ();
146
+ _currentTickAnimationController? .dispose ();
147
+ _currentTickBlinkingController? .dispose ();
148
+ _loadingAnimationController? .dispose ();
149
+ _topBoundQuoteAnimationController? .dispose ();
150
+ _bottomBoundQuoteAnimationController? .dispose ();
145
151
super .dispose ();
146
152
}
147
153
@@ -170,6 +176,16 @@ class _ChartState extends State<Chart> with TickerProviderStateMixin {
170
176
_setupCurrentTickAnimation ();
171
177
_setupBlinkingAnimation ();
172
178
_setupBoundsAnimation ();
179
+ _setupRightEpochAnimation ();
180
+ }
181
+
182
+ void _setupRightEpochAnimation () {
183
+ _rightEpochAnimationController = AnimationController .unbounded (
184
+ vsync: this ,
185
+ value: rightBoundEpoch.toDouble (),
186
+ )..addListener (() {
187
+ rightBoundEpoch = _rightEpochAnimationController.value.toInt ();
188
+ });
173
189
}
174
190
175
191
void _setupCurrentTickAnimation () {
@@ -333,7 +349,7 @@ class _ChartState extends State<Chart> with TickerProviderStateMixin {
333
349
);
334
350
}),
335
351
),
336
- if (! _shouldAutoPan )
352
+ if (_arrowButtonBeVisible )
337
353
Positioned (
338
354
bottom: 30 + timeLabelsAreaHeight,
339
355
right: 30 + quoteLabelsAreaWidth,
@@ -447,7 +463,20 @@ class _ChartState extends State<Chart> with TickerProviderStateMixin {
447
463
}
448
464
449
465
void _scrollToNow () {
450
- rightBoundEpoch = nowEpoch + _pxToMs (maxCurrentTickOffset);
466
+ final animationMsDuration = 600 ;
467
+ final lowerBound = rightBoundEpoch.toDouble ();
468
+ final upperBound = nowEpoch +
469
+ _pxToMs (maxCurrentTickOffset).toDouble () +
470
+ animationMsDuration;
471
+
472
+ if (upperBound > lowerBound) {
473
+ _rightEpochAnimationController.value = lowerBound;
474
+ _rightEpochAnimationController.animateTo (
475
+ upperBound,
476
+ curve: Curves .easeOut,
477
+ duration: Duration (milliseconds: animationMsDuration),
478
+ );
479
+ }
451
480
}
452
481
453
482
void _onScaleAndPanEnd (ScaleEndDetails details) {
0 commit comments