mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Reduced redundant calculations of animation in chart widget.
This commit is contained in:
parent
77695091b3
commit
d603f4de51
2 changed files with 79 additions and 87 deletions
|
@ -44,6 +44,19 @@ constexpr auto kHeightLimitsUpdateTimeout = crl::time(320);
|
||||||
return minValue;
|
return minValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Limits FindHeightLimitsBetweenXLimits(
|
||||||
|
Data::StatisticalChart &chartData,
|
||||||
|
const Limits &xPercentageLimits) {
|
||||||
|
const auto startXIndex = chartData.findStartIndex(xPercentageLimits.min);
|
||||||
|
const auto endXIndex = chartData.findEndIndex(
|
||||||
|
startXIndex,
|
||||||
|
xPercentageLimits.max);
|
||||||
|
return Limits{
|
||||||
|
float64(FindMinValue(chartData, startXIndex, endXIndex)),
|
||||||
|
float64(FindMaxValue(chartData, startXIndex, endXIndex)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
void PaintHorizontalLines(
|
void PaintHorizontalLines(
|
||||||
QPainter &p,
|
QPainter &p,
|
||||||
const ChartHorizontalLinesData &horizontalLine,
|
const ChartHorizontalLinesData &horizontalLine,
|
||||||
|
@ -84,6 +97,9 @@ public:
|
||||||
[[nodiscard]] rpl::producer<Limits> xPercentageLimitsChange() const;
|
[[nodiscard]] rpl::producer<Limits> xPercentageLimitsChange() const;
|
||||||
[[nodiscard]] rpl::producer<> userInteractionFinished() const;
|
[[nodiscard]] rpl::producer<> userInteractionFinished() const;
|
||||||
|
|
||||||
|
void setFullHeightLimits(Limits limits);
|
||||||
|
[[nodiscard]] const Limits &fullHeightLimits() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
not_null<Ui::AbstractButton*> _left;
|
not_null<Ui::AbstractButton*> _left;
|
||||||
not_null<Ui::AbstractButton*> _right;
|
not_null<Ui::AbstractButton*> _right;
|
||||||
|
@ -91,6 +107,8 @@ private:
|
||||||
rpl::event_stream<Limits> _xPercentageLimitsChange;
|
rpl::event_stream<Limits> _xPercentageLimitsChange;
|
||||||
rpl::event_stream<> _userInteractionFinished;
|
rpl::event_stream<> _userInteractionFinished;
|
||||||
|
|
||||||
|
Limits _fullHeightLimits;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int x = 0;
|
int x = 0;
|
||||||
int leftLimit = 0;
|
int leftLimit = 0;
|
||||||
|
@ -192,6 +210,14 @@ rpl::producer<> ChartWidget::Footer::userInteractionFinished() const {
|
||||||
return _userInteractionFinished.events();
|
return _userInteractionFinished.events();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChartWidget::Footer::setFullHeightLimits(Limits limits) {
|
||||||
|
_fullHeightLimits = std::move(limits);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Limits &ChartWidget::Footer::fullHeightLimits() const {
|
||||||
|
return _fullHeightLimits;
|
||||||
|
}
|
||||||
|
|
||||||
ChartWidget::ChartAnimationController::ChartAnimationController(
|
ChartWidget::ChartAnimationController::ChartAnimationController(
|
||||||
Fn<void()> &&updateCallback)
|
Fn<void()> &&updateCallback)
|
||||||
: _animation(std::move(updateCallback)) {
|
: _animation(std::move(updateCallback)) {
|
||||||
|
@ -201,35 +227,29 @@ void ChartWidget::ChartAnimationController::setXPercentageLimits(
|
||||||
Data::StatisticalChart &chartData,
|
Data::StatisticalChart &chartData,
|
||||||
Limits xPercentageLimits,
|
Limits xPercentageLimits,
|
||||||
crl::time now) {
|
crl::time now) {
|
||||||
if ((_animValueXMin.to() == xPercentageLimits.min)
|
if ((_animationValueXMin.to() == xPercentageLimits.min)
|
||||||
&& (_animValueXMax.to() == xPercentageLimits.max)) {
|
&& (_animationValueXMax.to() == xPercentageLimits.max)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
start();
|
start();
|
||||||
_animValueXMin.start(xPercentageLimits.min);
|
_animationValueXMin.start(xPercentageLimits.min);
|
||||||
_animValueXMax.start(xPercentageLimits.max);
|
_animationValueXMax.start(xPercentageLimits.max);
|
||||||
_lastUserInteracted = now;
|
_lastUserInteracted = now;
|
||||||
|
|
||||||
{
|
_finalHeightLimits = FindHeightLimitsBetweenXLimits(
|
||||||
const auto startXIndex = chartData.findStartIndex(
|
chartData,
|
||||||
_animValueXMin.to());
|
{ _animationValueXMin.to(), _animationValueXMax.to() });
|
||||||
const auto endXIndex = chartData.findEndIndex(
|
_animationValueHeightMin = anim::value(
|
||||||
startXIndex,
|
_animationValueHeightMin.current(),
|
||||||
_animValueXMax.to());
|
|
||||||
_finalHeightLimits = {
|
|
||||||
float64(FindMinValue(chartData, startXIndex, endXIndex)),
|
|
||||||
float64(FindMaxValue(chartData, startXIndex, endXIndex)),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
_animValueYMin = anim::value(
|
|
||||||
_animValueYMin.current(),
|
|
||||||
_finalHeightLimits.min);
|
_finalHeightLimits.min);
|
||||||
_animValueYMax = anim::value(
|
_animationValueHeightMax = anim::value(
|
||||||
_animValueYMax.current(),
|
_animationValueHeightMax.current(),
|
||||||
_finalHeightLimits.max);
|
_finalHeightLimits.max);
|
||||||
|
|
||||||
{
|
{
|
||||||
auto k = (_animValueYMax.current() - _animValueYMin.current())
|
const auto currentDelta = _animationValueHeightMax.current()
|
||||||
|
- _animationValueHeightMin.current();
|
||||||
|
auto k = currentDelta
|
||||||
/ float64(_finalHeightLimits.max - _finalHeightLimits.min);
|
/ float64(_finalHeightLimits.max - _finalHeightLimits.min);
|
||||||
if (k > 1.) {
|
if (k > 1.) {
|
||||||
k = 1. / k;
|
k = 1. / k;
|
||||||
|
@ -240,7 +260,7 @@ void ChartWidget::ChartAnimationController::setXPercentageLimits(
|
||||||
constexpr auto kDtHeightSpeedThreshold1 = 0.7;
|
constexpr auto kDtHeightSpeedThreshold1 = 0.7;
|
||||||
constexpr auto kDtHeightSpeedThreshold2 = 0.1;
|
constexpr auto kDtHeightSpeedThreshold2 = 0.1;
|
||||||
constexpr auto kDtHeightInstantThreshold = 0.97;
|
constexpr auto kDtHeightInstantThreshold = 0.97;
|
||||||
_dtYSpeed = (k > kDtHeightSpeedThreshold1)
|
_dtHeightSpeed = (k > kDtHeightSpeedThreshold1)
|
||||||
? kDtHeightSpeed1
|
? kDtHeightSpeed1
|
||||||
: (k < kDtHeightSpeedThreshold2)
|
: (k < kDtHeightSpeedThreshold2)
|
||||||
? kDtHeightSpeed2
|
? kDtHeightSpeed2
|
||||||
|
@ -259,10 +279,10 @@ void ChartWidget::ChartAnimationController::start() {
|
||||||
|
|
||||||
void ChartWidget::ChartAnimationController::finish() {
|
void ChartWidget::ChartAnimationController::finish() {
|
||||||
_animation.stop();
|
_animation.stop();
|
||||||
_animValueXMin.finish();
|
_animationValueXMin.finish();
|
||||||
_animValueXMax.finish();
|
_animationValueXMax.finish();
|
||||||
_animValueYMin.finish();
|
_animationValueHeightMin.finish();
|
||||||
_animValueYMax.finish();
|
_animationValueHeightMax.finish();
|
||||||
_animValueYAlpha.finish();
|
_animValueYAlpha.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,8 +310,8 @@ void ChartWidget::ChartAnimationController::tick(
|
||||||
_alphaAnimationStartedAt = now;
|
_alphaAnimationStartedAt = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
_dtCurrent.min = std::min(_dtCurrent.min + _dtYSpeed, 1.);
|
_dtCurrent.min = std::min(_dtCurrent.min + _dtHeightSpeed, 1.);
|
||||||
_dtCurrent.max = std::min(_dtCurrent.max + _dtYSpeed, 1.);
|
_dtCurrent.max = std::min(_dtCurrent.max + _dtHeightSpeed, 1.);
|
||||||
|
|
||||||
const auto dtX = std::min(
|
const auto dtX = std::min(
|
||||||
(now - _animation.started()) / kXExpandingDuration,
|
(now - _animation.started()) / kXExpandingDuration,
|
||||||
|
@ -304,35 +324,35 @@ void ChartWidget::ChartAnimationController::tick(
|
||||||
return anim.current() == anim.to();
|
return anim.current() == anim.to();
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto xFinished = isFinished(_animValueXMin)
|
const auto xFinished = isFinished(_animationValueXMin)
|
||||||
&& isFinished(_animValueXMax);
|
&& isFinished(_animationValueXMax);
|
||||||
const auto yFinished = isFinished(_animValueYMin)
|
const auto yFinished = isFinished(_animationValueHeightMin)
|
||||||
&& isFinished(_animValueYMax);
|
&& isFinished(_animationValueHeightMax);
|
||||||
const auto alphaFinished = isFinished(_animValueYAlpha);
|
const auto alphaFinished = isFinished(_animValueYAlpha);
|
||||||
|
|
||||||
if (xFinished && yFinished && alphaFinished) {
|
if (xFinished && yFinished && alphaFinished) {
|
||||||
const auto &lines = horizontalLines.back().lines;
|
const auto &lines = horizontalLines.back().lines;
|
||||||
if ((lines.front().absoluteValue == _animValueYMin.to())
|
if ((lines.front().absoluteValue == _animationValueHeightMin.to())
|
||||||
&& (lines.back().absoluteValue == _animValueYMax.to())) {
|
&& lines.back().absoluteValue == _animationValueHeightMax.to()) {
|
||||||
_animation.stop();
|
_animation.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (xFinished) {
|
if (xFinished) {
|
||||||
_animValueXMin.finish();
|
_animationValueXMin.finish();
|
||||||
_animValueXMax.finish();
|
_animationValueXMax.finish();
|
||||||
} else {
|
} else {
|
||||||
_animValueXMin.update(dtX, anim::linear);
|
_animationValueXMin.update(dtX, anim::linear);
|
||||||
_animValueXMax.update(dtX, anim::linear);
|
_animationValueXMax.update(dtX, anim::linear);
|
||||||
}
|
}
|
||||||
if (_heightAnimationStarted) {
|
if (_heightAnimationStarted) {
|
||||||
_animValueYMin.update(_dtCurrent.min, anim::easeInCubic);
|
_animationValueHeightMin.update(_dtCurrent.min, anim::easeInCubic);
|
||||||
_animValueYMax.update(_dtCurrent.max, anim::easeInCubic);
|
_animationValueHeightMax.update(_dtCurrent.max, anim::easeInCubic);
|
||||||
_animValueYAlpha.update(dtAlpha, anim::easeInCubic);
|
_animValueYAlpha.update(dtAlpha, anim::easeInCubic);
|
||||||
|
|
||||||
for (auto &horizontalLine : horizontalLines) {
|
for (auto &horizontalLine : horizontalLines) {
|
||||||
horizontalLine.computeRelative(
|
horizontalLine.computeRelative(
|
||||||
_animValueYMax.current(),
|
_animationValueHeightMax.current(),
|
||||||
_animValueYMin.current());
|
_animationValueHeightMin.current());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,11 +382,14 @@ void ChartWidget::ChartAnimationController::tick(
|
||||||
}
|
}
|
||||||
|
|
||||||
Limits ChartWidget::ChartAnimationController::currentXLimits() const {
|
Limits ChartWidget::ChartAnimationController::currentXLimits() const {
|
||||||
return { _animValueXMin.current(), _animValueXMax.current() };
|
return { _animationValueXMin.current(), _animationValueXMax.current() };
|
||||||
}
|
}
|
||||||
|
|
||||||
Limits ChartWidget::ChartAnimationController::currentHeightLimits() const {
|
Limits ChartWidget::ChartAnimationController::currentHeightLimits() const {
|
||||||
return { _animValueYMin.current(), _animValueYMax.current() };
|
return {
|
||||||
|
_animationValueHeightMin.current(),
|
||||||
|
_animationValueHeightMax.current(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Limits ChartWidget::ChartAnimationController::finalHeightLimits() const {
|
Limits ChartWidget::ChartAnimationController::finalHeightLimits() const {
|
||||||
|
@ -391,22 +414,16 @@ ChartWidget::ChartWidget(not_null<Ui::RpWidget*> parent)
|
||||||
st::countryRowHeight);
|
st::countryRowHeight);
|
||||||
}, _footer->lifetime());
|
}, _footer->lifetime());
|
||||||
_footer->paintRequest(
|
_footer->paintRequest(
|
||||||
) | rpl::start_with_next([=, limits = Limits{ 0., 1. }] {
|
) | rpl::start_with_next([=, fullXLimits = Limits{ 0., 1. }] {
|
||||||
auto p = QPainter(_footer.get());
|
auto p = QPainter(_footer.get());
|
||||||
|
|
||||||
if (_chartData) {
|
if (_chartData) {
|
||||||
const auto startXIndex2 = 0;
|
|
||||||
const auto endXIndex2 = int(_chartData.xPercentage.size() - 1);
|
|
||||||
const auto limitsY = Limits{
|
|
||||||
float64(FindMinValue(_chartData, startXIndex2, endXIndex2)),
|
|
||||||
float64(FindMaxValue(_chartData, startXIndex2, endXIndex2)),
|
|
||||||
};
|
|
||||||
p.fillRect(_footer->rect(), st::boxBg);
|
p.fillRect(_footer->rect(), st::boxBg);
|
||||||
Statistic::PaintLinearChartView(
|
Statistic::PaintLinearChartView(
|
||||||
p,
|
p,
|
||||||
_chartData,
|
_chartData,
|
||||||
limits,
|
fullXLimits,
|
||||||
limitsY,
|
_footer->fullHeightLimits(),
|
||||||
_footer->rect());
|
_footer->rect());
|
||||||
}
|
}
|
||||||
}, _footer->lifetime());
|
}, _footer->lifetime());
|
||||||
|
@ -438,7 +455,11 @@ ChartWidget::ChartWidget(not_null<Ui::RpWidget*> parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChartWidget::setChartData(Data::StatisticalChart chartData) {
|
void ChartWidget::setChartData(Data::StatisticalChart chartData) {
|
||||||
_chartData = chartData;
|
_chartData = std::move(chartData);
|
||||||
|
|
||||||
|
_footer->setFullHeightLimits(FindHeightLimitsBetweenXLimits(
|
||||||
|
_chartData,
|
||||||
|
{ _chartData.xPercentage.front(), _chartData.xPercentage.back() }));
|
||||||
|
|
||||||
_animationController.setXPercentageLimits(
|
_animationController.setXPercentageLimits(
|
||||||
_chartData,
|
_chartData,
|
||||||
|
|
|
@ -57,16 +57,16 @@ private:
|
||||||
crl::time _alphaAnimationStartedAt = 0;
|
crl::time _alphaAnimationStartedAt = 0;
|
||||||
bool _heightAnimationStarted = false;
|
bool _heightAnimationStarted = false;
|
||||||
|
|
||||||
anim::value _animValueXMin;
|
anim::value _animationValueXMin;
|
||||||
anim::value _animValueXMax;
|
anim::value _animationValueXMax;
|
||||||
anim::value _animValueYMin;
|
anim::value _animationValueHeightMin;
|
||||||
anim::value _animValueYMax;
|
anim::value _animationValueHeightMax;
|
||||||
|
|
||||||
anim::value _animValueYAlpha;
|
anim::value _animValueYAlpha;
|
||||||
|
|
||||||
Limits _finalHeightLimits;
|
Limits _finalHeightLimits;
|
||||||
|
|
||||||
float _dtYSpeed = 0.;
|
float _dtHeightSpeed = 0.;
|
||||||
Limits _dtCurrent;
|
Limits _dtCurrent;
|
||||||
|
|
||||||
rpl::event_stream<> _heightAnimationStarts;
|
rpl::event_stream<> _heightAnimationStarts;
|
||||||
|
@ -78,40 +78,11 @@ private:
|
||||||
|
|
||||||
bool _useMinHeight = false;
|
bool _useMinHeight = false;
|
||||||
|
|
||||||
Limits _currentHeight;
|
|
||||||
Limits _animateToHeight;
|
|
||||||
Limits _thresholdHeight = { -1, 0 };
|
|
||||||
Limits _startFrom;
|
|
||||||
Limits _startFromH;
|
|
||||||
|
|
||||||
Limits _xPercentageLimits;
|
|
||||||
// struct {
|
|
||||||
// Ui::Animations::Basic animation;
|
|
||||||
|
|
||||||
// crl::time lastUserInteracted = 0;
|
|
||||||
// crl::time yAnimationStartedAt = 0;
|
|
||||||
// crl::time alphaAnimationStartedAt = 0;
|
|
||||||
|
|
||||||
// anim::value animValueXMin;
|
|
||||||
// anim::value animValueXMax;
|
|
||||||
// anim::value animValueYMin;
|
|
||||||
// anim::value animValueYMax;
|
|
||||||
|
|
||||||
// anim::value animValueYAlpha;
|
|
||||||
|
|
||||||
// float dtYSpeed = 0.;
|
|
||||||
// Limits dtCurrent;
|
|
||||||
// } _xPercentage;
|
|
||||||
ChartAnimationController _animationController;
|
ChartAnimationController _animationController;
|
||||||
|
|
||||||
float64 _minMaxUpdateStep = 0.;
|
|
||||||
|
|
||||||
crl::time _lastHeightLimitsChanged = 0;
|
crl::time _lastHeightLimitsChanged = 0;
|
||||||
|
|
||||||
std::vector<ChartHorizontalLinesData> _horizontalLines;
|
std::vector<ChartHorizontalLinesData> _horizontalLines;
|
||||||
|
|
||||||
Ui::Animations::Simple _heightLimitsAnimation;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Statistic
|
} // namespace Statistic
|
||||||
|
|
Loading…
Add table
Reference in a new issue