1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <QtCore/QPointF>
5#include <QtGraphs/QLineSeries>
6#include "private/qgraphpointanimation_p.h"
7#include "private/qgraphtransition_p.h"
8#include "private/qxyseries_p.h"
9
10/*!
11 \qmltype GraphPointAnimation
12 \inqmlmodule QtGraphs
13 \ingroup graphs_qml_2D
14 \brief An animation type which signifies the animation for points.
15
16GraphPointAnimation is an animation type derived from QVariantAnimation which defines how points are animated.
17It can make use of QVariantAnimation functionality and properties for its animations, such as \c duration and \c easing.
18These animations are housed inside of a QParallelAnimationGroup and hence will run in parallel.
19
20This example shows how to use a GraphPointAnimation to set points to animate with
21a \c duration of 1000ms and \c easing of OutCubic:
22
23\snippet doc_src_qmlgraphs.cpp 12
24
25For XYSeries, this is considered to be the main list of points defined inside
26the series. The point is linearly interpolated from the start to the end value.
27
28\sa GraphTransition, SplineControlAnimation
29
30*/
31
32QGraphPointAnimation::QGraphPointAnimation(QObject *parent)
33 : QXYSeriesAnimation(parent)
34{
35 setDuration(800);
36 setEasingCurve(QEasingCurve::OutCubic);
37}
38
39QGraphPointAnimation::~QGraphPointAnimation() {}
40
41QGraphAnimation::GraphAnimationType QGraphPointAnimation::animationType()
42{
43 return QGraphAnimation::GraphAnimationType::GraphPoint;
44}
45
46void QGraphPointAnimation::setAnimatingValue(const QVariant &start, const QVariant &end)
47{
48 setStartValue(start);
49 setEndValue(end);
50}
51
52QVariant QGraphPointAnimation::interpolated(const QVariant &start,
53 const QVariant &end,
54 qreal progress) const
55{
56 auto startPoint = qvariant_cast<QPointF>(v: start);
57 auto endPoint = qvariant_cast<QPointF>(v: end);
58
59 auto interpolatedPoint = QPointF{
60 qreal(startPoint.x() * (1.0 - progress) + endPoint.x() * progress),
61 qreal(startPoint.y() * (1.0 - progress) + endPoint.y() * progress),
62 };
63
64 return QVariant::fromValue(value: interpolatedPoint);
65}
66
67void QGraphPointAnimation::animate()
68{
69 // Hierarchy should look like GraphAnimation -> ParallelAnimationGroup -> GraphTransition -> QXYSeries
70 auto series = qobject_cast<QXYSeries *>(object: parent()->parent()->parent());
71
72 if (!series)
73 return;
74
75 if (animating() == QGraphAnimation::AnimationState::Playing) {
76 end();
77 m_activePointIndex = m_newPointIndex;
78 }
79
80 setAnimating(QGraphAnimation::AnimationState::Playing);
81
82 auto &pointList = series->d_func()->m_points;
83
84 switch (m_currentTransitionType) {
85 default:
86 case QGraphTransition::TransitionType::PointAdded: {
87 pointList.append(t: series->points().size() >= 1 ? pointList.last() : m_newPoint);
88
89 auto startv = QVariant::fromValue(value: pointList.last());
90 auto endv = QVariant::fromValue(value: m_newPoint);
91
92 setAnimatingValue(start: startv, end: endv);
93 } break;
94 case QGraphTransition::TransitionType::PointReplaced: {
95 auto startv = QVariant::fromValue(value: pointList[m_activePointIndex]);
96 auto endv = QVariant::fromValue(value: m_newPoint);
97
98 setAnimatingValue(start: startv, end: endv);
99 } break;
100 case QGraphTransition::TransitionType::PointRemoved: {
101 if (series->points().size() < 1)
102 break;
103
104 auto startv = QVariant::fromValue(value: pointList[pointList.size() - 1]);
105 auto endv = QVariant::fromValue(
106 value: pointList[pointList.size() > 1 ? pointList.size() - 2 : pointList.size() - 1]);
107
108 setAnimatingValue(start: startv, end: endv);
109 } break;
110 }
111
112 m_previousTransitionType = m_currentTransitionType;
113}
114
115void QGraphPointAnimation::end()
116{
117 auto series = qobject_cast<QXYSeries *>(object: parent()->parent()->parent());
118
119 if (!series || animating() == QGraphAnimation::AnimationState::Stopped) {
120 m_previousTransitionType = m_currentTransitionType;
121 return;
122 }
123
124 setAnimating(QGraphAnimation::AnimationState::Stopped);
125 stop();
126
127 auto &points = series->d_func()->m_points;
128
129 switch (m_previousTransitionType) {
130 default:
131 case QGraphTransition::TransitionType::PointAdded: {
132 points.replace(i: m_activePointIndex, t: qvariant_cast<QPointF>(v: endValue()));
133 emit series->pointAdded(index: points.size() - 1);
134 emit series->countChanged();
135 } break;
136 case QGraphTransition::TransitionType::PointReplaced: {
137 points.replace(i: m_activePointIndex, t: qvariant_cast<QPointF>(v: endValue()));
138 emit series->pointReplaced(index: m_activePointIndex);
139 } break;
140 case QGraphTransition::TransitionType::PointRemoved: {
141 points.remove(i: points.size() - 1);
142 emit series->countChanged();
143 emit series->pointRemoved(index: points.size() - 1);
144 } break;
145 }
146
147 m_previousTransitionType = m_currentTransitionType;
148 emit series->update();
149}
150
151void QGraphPointAnimation::valueUpdated(const QVariant &value)
152{
153 auto series = qobject_cast<QXYSeries *>(object: parent()->parent()->parent());
154
155 if (!series)
156 return;
157
158 auto val = qvariant_cast<QPointF>(v: value);
159 auto &points = series->d_func()->m_points;
160
161 switch (m_currentTransitionType) {
162 default:
163 case QGraphTransition::TransitionType::PointAdded: {
164 points.replace(i: m_activePointIndex, t: val);
165 } break;
166 case QGraphTransition::TransitionType::PointReplaced: {
167 points.replace(i: m_activePointIndex, t: val);
168 } break;
169 case QGraphTransition::TransitionType::PointRemoved: {
170 if (points.size() > 1)
171 points.replace(i: points.size() - 1, t: val);
172 } break;
173 }
174
175 emit series->update();
176}
177

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtgraphs/src/graphs2d/animation/qgraphpointanimation.cpp