Added fade animation to details widget on charts.

This commit is contained in:
23rd 2023-07-07 14:41:30 +03:00 committed by John Preston
parent 74aae29b64
commit 07cd35b1a8
5 changed files with 60 additions and 11 deletions

View File

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "statistics/point_details_widget.h"
#include "ui/abstract_button.h"
#include "ui/effects/animation_value_f.h"
#include "ui/painter.h"
#include "ui/rect.h"
#include "styles/style_boxes.h"
@ -20,6 +21,7 @@ namespace Statistic {
namespace {
constexpr auto kHeightLimitsUpdateTimeout = crl::time(320);
constexpr auto kExpandingDelay = crl::time(100);
inline float64 InterpolationRatio(float64 from, float64 to, float64 result) {
return (result - from) / (to - from);
@ -341,7 +343,6 @@ void ChartWidget::ChartAnimationController::tick(
if (!_animation.animating()) {
return;
}
constexpr auto kExpandingDelay = crl::time(100);
constexpr auto kXExpandingDuration = 200.;
constexpr auto kAlphaExpandingDuration = 200.;
@ -444,6 +445,20 @@ Limits ChartWidget::ChartAnimationController::finalHeightLimits() const {
return _finalHeightLimits;
}
float64 ChartWidget::ChartAnimationController::detailsProgress(
crl::time now) const {
return _animation.animating()
? std::clamp(
(now - _animation.started()) / float64(kExpandingDelay),
0.,
1.)
: 0.;
}
bool ChartWidget::ChartAnimationController::animating() const {
return _animation.animating();
}
auto ChartWidget::ChartAnimationController::heightAnimationStarts() const
-> rpl::producer<> {
return _heightAnimationStarts.events();
@ -488,7 +503,9 @@ void ChartWidget::setupChartArea() {
) | rpl::start_with_next([=](const QRect &r) {
auto p = QPainter(_chartArea.get());
_animationController.tick(crl::now(), _horizontalLines);
const auto now = crl::now();
_animationController.tick(now, _horizontalLines);
const auto chartRect = chartAreaRect();
@ -498,14 +515,25 @@ void ChartWidget::setupChartArea() {
PaintHorizontalLines(p, horizontalLine, chartRect);
}
if (_details.currentX) {
const auto lineRect = QRectF(
_details.currentX - (st::lineWidth / 2.),
0,
st::lineWidth,
_chartArea->height());
p.setOpacity(1.);
p.fillRect(lineRect, st::windowSubTextFg);
const auto detailsAlpha = 1.
- _animationController.detailsProgress(now);
if (_details.widget) {
if (!detailsAlpha && _details.currentX) {
_details.widget->hide();
_details.widget->setXIndex(-1);
_details.currentX = 0;
}
if (_details.currentX) {
const auto lineRect = QRectF(
_details.currentX - (st::lineWidth / 2.),
0,
st::lineWidth,
_chartArea->height());
const auto opacity = ScopedPainterOpacity(p, detailsAlpha);
p.fillRect(lineRect, st::windowSubTextFg);
_details.widget->setAlpha(detailsAlpha);
}
}
if (_chartData) {
@ -515,7 +543,10 @@ void ChartWidget::setupChartArea() {
_animationController.currentXLimits(),
_animationController.currentHeightLimits(),
chartRect,
{ _details.widget ? _details.widget->xIndex() : -1, 1. });
{
_details.widget ? _details.widget->xIndex() : -1,
detailsAlpha,
});
}
for (auto &horizontalLine : _horizontalLines) {
@ -578,6 +609,9 @@ void ChartWidget::setupDetails() {
_chartArea->mouseStateChanged(
) | rpl::start_with_next([=](const RpMouseWidget::State &state) {
if (_animationController.animating()) {
return;
}
switch (state.mouseState) {
case QEvent::MouseButtonPress:
case QEvent::MouseMove: {

View File

@ -48,6 +48,8 @@ private:
[[nodiscard]] Limits finalXLimits() const;
[[nodiscard]] Limits currentHeightLimits() const;
[[nodiscard]] Limits finalHeightLimits() const;
[[nodiscard]] float64 detailsProgress(crl::time now) const;
[[nodiscard]] bool animating() const;
[[nodiscard]] rpl::producer<> heightAnimationStarts() const;

View File

@ -74,6 +74,7 @@ void PaintLinearChartView(
p.drawPath(chartPath);
if (!detailsDotPoint.isNull()) {
ScopedPainterOpacity o(p, detailsPaintContext.progress);
p.setBrush(st::boxBg);
const auto r = st::statisticsDetailsDotRadius;
p.drawEllipse(detailsDotPoint, r, r);

View File

@ -43,6 +43,9 @@ int PointDetailsWidget::xIndex() const {
void PointDetailsWidget::setXIndex(int xIndex) {
_xIndex = xIndex;
if (xIndex < 0) {
return;
}
_header.setText(_headerStyle, _chartData.getDayString(xIndex));
_lines.clear();
@ -58,6 +61,11 @@ void PointDetailsWidget::setXIndex(int xIndex) {
}
}
void PointDetailsWidget::setAlpha(float64 alpha) {
_alpha = alpha;
update();
}
int PointDetailsWidget::lineYAt(int i) const {
return _textRect.y()
+ _headerStyle.font->height
@ -69,6 +77,8 @@ int PointDetailsWidget::lineYAt(int i) const {
void PointDetailsWidget::paintEvent(QPaintEvent *e) {
auto p = QPainter(this);
p.setOpacity(_alpha);
const auto fullRect = rect();
Ui::Shadow::paint(p, _innerRect, width(), st::boxRoundShadow);

View File

@ -20,6 +20,7 @@ public:
[[nodiscard]] int xIndex() const;
void setXIndex(int xIndex);
void setAlpha(float64 alpha);
protected:
void paintEvent(QPaintEvent *e) override;
@ -42,6 +43,7 @@ private:
QRect _textRect;
int _xIndex = -1;
float64 _alpha = 1.;
std::vector<Line> _lines;