1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/QPointF>
#include "QSplineSeries"
#include "private/qsplinecontrolanimation_p.h"
#include "private/qsplineseries_p.h"
/*!
\qmltype SplineControlAnimation
\inqmlmodule QtGraphs
\ingroup graphs_qml_2D
\inherits XYSeriesAnimation
\brief An animation type which signifies the animation for spline control points.
SplineControlAnimation is an animation type derived from QVariantAnimation which defines how spline control points
are animated. It can make use of QVariantAnimation functionality and properties for its animations, such as \c duration
and \c easing. These animations are housed inside a QParallelAnimationGroup and hence will run in parallel.
This animation will not affect the main points of the SplineSeries, but only the two control handles
on either side of the point. Each of the control points are linearly interpolated in succession.
This example shows how to use both a SplineControlPointAnimation and a
GraphPointAnimation to define animations for both the main series of points and the
control points of a SplineSeries:
\snippet doc_src_qmlgraphs.cpp 13
\sa GraphTransition, GraphPointAnimation
*/
QSplineControlAnimation::QSplineControlAnimation(QObject *parent)
: QXYSeriesAnimation(parent)
{
setDuration(800);
setEasingCurve(QEasingCurve::OutCubic);
}
QSplineControlAnimation::~QSplineControlAnimation() {}
QGraphAnimation::GraphAnimationType QSplineControlAnimation::animationType()
{
return QGraphAnimation::GraphAnimationType::ControlPoint;
}
void QSplineControlAnimation::setAnimatingValue(const QVariant &start, const QVariant &end)
{
setStartValue(start);
setEndValue(end);
}
QVariant QSplineControlAnimation::interpolated(const QVariant &start,
const QVariant &end,
qreal progress) const
{
auto startList = qvariant_cast<QList<QPointF>>(start);
auto endList = qvariant_cast<QList<QPointF>>(end);
auto interpolateList = QList<QPointF>();
for (int i = 0; i < qMin(startList.size(), endList.size()); ++i) {
interpolateList.push_back(
{qreal(startList[i].x() * (1.0 - progress) + endList[i].x() * progress),
qreal(startList[i].y() * (1.0 - progress) + endList[i].y() * progress)});
}
return QVariant::fromValue(interpolateList);
}
void QSplineControlAnimation::animate()
{
// Hierarchy should look like GraphAnimation -> ParallelAnimationGroup -> GraphTransition -> SplineSeries
auto series = qobject_cast<QSplineSeries *>(parent()->parent()->parent());
if (!series || series->points().size() < 1) {
qCDebug(lcAnimation, "Series is nullptr or series point list is empty");
return;
}
auto pointList = series->points();
auto &cPoints = series->d_func()->m_controlPoints;
if (animating() == QGraphAnimation::AnimationState::Playing)
end();
setAnimating(QGraphAnimation::AnimationState::Playing);
auto oldPoints = cPoints;
series->d_func()->calculateSplinePoints();
while (oldPoints.size() < cPoints.size()) {
// Each point corresponds to a 2n - 1 control point pair other than the first
// (Except when there are only 2 points)
// 0 ---- 0
// 1 ---- 1
// ---- 2
// 2 ---- 3
// ---- 4 ...
QPointF point = pointList[oldPoints.size() / 2];
oldPoints.append(point);
}
auto varStart = QVariant::fromValue(oldPoints);
auto varEnd = QVariant::fromValue(cPoints);
setAnimatingValue(varStart, varEnd);
}
void QSplineControlAnimation::end()
{
auto series = qobject_cast<QSplineSeries *>(parent()->parent()->parent());
if (!series || animating() == QGraphAnimation::AnimationState::Stopped)
return;
setAnimating(QGraphAnimation::AnimationState::Stopped);
stop();
series->d_func()->calculateSplinePoints();
emit series->update();
}
void QSplineControlAnimation::valueUpdated(const QVariant &value)
{
auto series = qobject_cast<QSplineSeries *>(parent()->parent()->parent());
if (!series)
return;
auto &cPoints = series->d_func()->m_controlPoints;
auto points = qvariant_cast<QList<QPointF>>(value);
for (int i = 0; i < qMin(points.size(), cPoints.size()); ++i)
cPoints.replace(i, points[i]);
emit series->update();
}
|