From fc973c6ca45bd55122b7e2af8d38c4c11ab044a1 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 24 Jan 2012 11:40:02 +1000 Subject: [PATCH] Update PathAnimation API and document. Update the API according to the last API review. Document it and add a basic example as well. Change-Id: I2d06a0772a9fb2101844446e68799620c275db97 Reviewed-by: Yunqiao Yin --- .../animation/pathanimation/pathanimation.qml | 108 ++++++++++++++++ src/quick/items/qquickanimation.cpp | 141 ++++++++++++++++++--- src/quick/items/qquickanimation_p.h | 16 +-- src/quick/items/qquickanimation_p_p.h | 6 +- .../qdeclarativeanimations/data/pathAnimation2.qml | 4 +- 5 files changed, 247 insertions(+), 28 deletions(-) create mode 100644 examples/declarative/animation/pathanimation/pathanimation.qml diff --git a/examples/declarative/animation/pathanimation/pathanimation.qml b/examples/declarative/animation/pathanimation/pathanimation.qml new file mode 100644 index 0000000..3cf12b0 --- /dev/null +++ b/examples/declarative/animation/pathanimation/pathanimation.qml @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Rectangle { + id: window + width: 400 + height: 400 + + Canvas { + id: canvas + anchors.fill: parent + smooth: true + + onPaint: { + context.clearRect(0, 0, width, height) + context.strokeStyle = "black" + context.path = pathAnim.path + context.stroke() + } + } + + PathAnimation { + id: pathAnim + + duration: 2000 + easing.type: Easing.InQuad + + target: box + orientation: PathAnimation.RightFirst + anchorPoint: Qt.point(box.width/2, box.height/2) + path: Path { + startX: 50; startY: 50 + + PathCubic { + x: window.width - 50 + y: window.height - 50 + + control1X: x; control1Y: 50 + control2X: 50; control2Y: y + } + + onChanged: canvas.requestPaint() + } + } + + Rectangle { + id: box + + x: 25; y: 25 + width: 50; height: 50 + border.width: 1 + smooth: true + + Text { + anchors.centerIn: parent + text: "Box" + } + } + + MouseArea { + anchors.fill: parent + onClicked: pathAnim.restart() + } + + Text { + text: "Click anywhere to animate along the path" + anchors.horizontalCenter: parent.horizontalCenter + } +} diff --git a/src/quick/items/qquickanimation.cpp b/src/quick/items/qquickanimation.cpp index 4fca68c..744c420 100644 --- a/src/quick/items/qquickanimation.cpp +++ b/src/quick/items/qquickanimation.cpp @@ -565,6 +565,31 @@ void QQuickAnchorAnimation::transition(QDeclarativeStateActions &actions, } } +/*! + \qmlclass PathAnimation QQuickPathAnimation + \inqmlmodule QtQuick 2 + \ingroup qml-animation-transition + \inherits Animation + \since QtQuick 2.0 + \brief The PathAnimation element animates an item along a path. + + When used in a transition, the path can be specified without start + or end points, for example: + \qml + PathAnimation { + path: Path { + //no startX, startY + PathCurve { x: 100; y: 100} + PathCurve {} //last element is empty with no end point specified + } + } + \endqml + + In the above case, the path start will be the item's current position, and the + path end will be the item's target position in the target state. + + \sa {QML Animation and Transitions}, PathInterpolator +*/ QQuickPathAnimation::QQuickPathAnimation(QObject *parent) : QDeclarativeAbstractAnimation(*(new QQuickPathAnimationPrivate), parent) { @@ -577,6 +602,12 @@ QQuickPathAnimation::~QQuickPathAnimation() { } +/*! + \qmlproperty int QtQuick2::PathAnimation::duration + This property holds the duration of the animation, in milliseconds. + + The default value is 250. +*/ int QQuickPathAnimation::duration() const { Q_D(const QQuickPathAnimation); @@ -597,6 +628,20 @@ void QQuickPathAnimation::setDuration(int duration) emit durationChanged(duration); } +/*! + \qmlproperty enumeration QtQuick2::PathAnimation::easing.type + \qmlproperty real QtQuick2::PathAnimation::easing.amplitude + \qmlproperty list QtQuick2::PathAnimation::easing.bezierCurve + \qmlproperty real QtQuick2::PathAnimation::easing.overshoot + \qmlproperty real QtQuick2::PathAnimation::easing.period + \brief the easing curve used for the animation. + + To specify an easing curve you need to specify at least the type. For some curves you can also specify + amplitude, period, overshoot or custom bezierCurve data. The default easing curve is \c Easing.Linear. + + See the \l{PropertyAnimation::easing.type} documentation for information + about the different types of easing curves. +*/ QEasingCurve QQuickPathAnimation::easing() const { Q_D(const QQuickPathAnimation); @@ -613,6 +658,12 @@ void QQuickPathAnimation::setEasing(const QEasingCurve &e) emit easingChanged(e); } +/*! + \qmlproperty Path QtQuick2::PathAnimation::path + This property holds the path to animate along. + + For more information on defining a path see the \l Path documentation. +*/ QDeclarativePath *QQuickPathAnimation::path() const { Q_D(const QQuickPathAnimation); @@ -629,6 +680,10 @@ void QQuickPathAnimation::setPath(QDeclarativePath *path) emit pathChanged(); } +/*! + \qmlproperty Item QtQuick2::PathAnimation::target + This property holds the item to animate. +*/ QQuickItem *QQuickPathAnimation::target() const { Q_D(const QQuickPathAnimation); @@ -645,6 +700,22 @@ void QQuickPathAnimation::setTarget(QQuickItem *target) emit targetChanged(); } +/*! + \qmlproperty enumeration QtQuick2::PathAnimation::orientation + This property controls the rotation of the item as it animates along the path. + + If a value other than \c Fixed is specified, the PathAnimation will rotate the + item to achieve the specified orientation as it travels along the path. + + \list + \o PathAnimation.Fixed (default) - the PathAnimation will not control + the rotation of the item. + \o PathAnimation.RightFirst - The right side of the item will lead along the path. + \o PathAnimation.LeftFirst - The left side of the item will lead along the path. + \o PathAnimation.BottomFirst - The bottom of the item will lead along the path. + \o PathAnimation.TopFirst - The top of the item will lead along the path. + \endlist +*/ QQuickPathAnimation::Orientation QQuickPathAnimation::orientation() const { Q_D(const QQuickPathAnimation); @@ -661,6 +732,15 @@ void QQuickPathAnimation::setOrientation(Orientation orientation) emit orientationChanged(d->orientation); } +/*! + \qmlproperty point QtQuick2::PathAnimation::anchorPoint + This property holds the anchor point for the item being animated. + + By default, the upper-left corner of the target (its 0,0 point) + will be anchored to (or follow) the path. The anchorPoint property can be used to + specify a different point for anchoring. For example, specifying an anchorPoint of + 5,5 for a 10x10 item means the center of the item will follow the path. +*/ QPointF QQuickPathAnimation::anchorPoint() const { Q_D(const QQuickPathAnimation); @@ -677,36 +757,66 @@ void QQuickPathAnimation::setAnchorPoint(const QPointF &point) emit anchorPointChanged(point); } -qreal QQuickPathAnimation::orientationEntryInterval() const +/*! + \qmlproperty real QtQuick2::PathAnimation::orientationEntryDuration + This property holds the duration (in milliseconds) of the transition in to the orientation. + + If an orientation has been specified for the PathAnimation, and the starting + rotation of the item does not match that given by the orientation, + orientationEntryDuration can be used to smoothly transition from the item's + starting rotation to the rotation given by the path orientation. +*/ +int QQuickPathAnimation::orientationEntryDuration() const { Q_D(const QQuickPathAnimation); - return d->entryInterval; + return d->entryDuration; } -void QQuickPathAnimation::setOrientationEntryInterval(qreal interval) +void QQuickPathAnimation::setOrientationEntryDuration(int duration) { Q_D(QQuickPathAnimation); - if (d->entryInterval == interval) + if (d->entryDuration == duration) return; - d->entryInterval = interval; - emit orientationEntryIntervalChanged(interval); + d->entryDuration = duration; + emit orientationEntryDurationChanged(duration); } -qreal QQuickPathAnimation::orientationExitInterval() const +/*! + \qmlproperty real QtQuick2::PathAnimation::orientationExitDuration + This property holds the duration (in milliseconds) of the transition out of the orientation. + + If an orientation and endRotation have been specified for the PathAnimation, + orientationExitDuration can be used to smoothly transition from the rotation given + by the path orientation to the specified endRotation. +*/ +int QQuickPathAnimation::orientationExitDuration() const { Q_D(const QQuickPathAnimation); - return d->exitInterval; + return d->exitDuration; } -void QQuickPathAnimation::setOrientationExitInterval(qreal interval) +void QQuickPathAnimation::setOrientationExitDuration(int duration) { Q_D(QQuickPathAnimation); - if (d->exitInterval == interval) + if (d->exitDuration == duration) return; - d->exitInterval = interval; - emit orientationExitIntervalChanged(interval); + d->exitDuration = duration; + emit orientationExitDurationChanged(duration); } +/*! + \qmlproperty real QtQuick2::PathAnimation::endRotation + This property holds the ending rotation for the target. + + If an orientation has been specified for the PathAnimation, + and the path doesn't end with the item at the desired rotation, + the endRotation property can be used to manually specify an end + rotation. + + This property is typically used with orientationExitDuration, as specifying + an endRotation without an orientationExitDuration may cause a jump to + the final rotation, rather than a smooth transition. +*/ qreal QQuickPathAnimation::endRotation() const { Q_D(const QQuickPathAnimation); @@ -739,8 +849,8 @@ void QQuickPathAnimation::transition(QDeclarativeStateActions &actions, data->orientation = d->orientation; data->anchorPoint = d->anchorPoint; - data->entryInterval = d->entryInterval; - data->exitInterval = d->exitInterval; + data->entryInterval = duration() ? qreal(d->entryDuration) / duration() : qreal(0); + data->exitInterval = duration() ? qreal(d->exitDuration) / duration() : qreal(0); data->endRotation = d->endRotation; data->reverse = direction == Backward ? true : false; data->fromSourced = false; @@ -885,6 +995,7 @@ void QQuickPathAnimationUpdater::setValue(qreal v) } //smoothly transition to the desired orientation + //TODO: shortest distance calculations if (startRotation.isValid()) { if (reverse && v == 0.0) angle = startRotation; @@ -892,7 +1003,7 @@ void QQuickPathAnimationUpdater::setValue(qreal v) angle = angle * v / entryInterval + startRotation * (entryInterval - v) / entryInterval; } if (endRotation.isValid()) { - qreal exitStart = 1 - exitInterval; + qreal exitStart = 1 - entryInterval; if (!reverse && v == 1.0) angle = endRotation; else if (v > exitStart) diff --git a/src/quick/items/qquickanimation_p.h b/src/quick/items/qquickanimation_p.h index 05d4ff6..b293b88 100644 --- a/src/quick/items/qquickanimation_p.h +++ b/src/quick/items/qquickanimation_p.h @@ -134,8 +134,8 @@ class Q_AUTOTEST_EXPORT QQuickPathAnimation : public QDeclarativeAbstractAnimati Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged) Q_PROPERTY(Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged) Q_PROPERTY(QPointF anchorPoint READ anchorPoint WRITE setAnchorPoint NOTIFY anchorPointChanged) - Q_PROPERTY(qreal orientationEntryInterval READ orientationEntryInterval WRITE setOrientationEntryInterval NOTIFY orientationEntryIntervalChanged) - Q_PROPERTY(qreal orientationExitInterval READ orientationExitInterval WRITE setOrientationExitInterval NOTIFY orientationExitIntervalChanged) + Q_PROPERTY(int orientationEntryDuration READ orientationEntryDuration WRITE setOrientationEntryDuration NOTIFY orientationEntryDurationChanged) + Q_PROPERTY(int orientationExitDuration READ orientationExitDuration WRITE setOrientationExitDuration NOTIFY orientationExitDurationChanged) Q_PROPERTY(qreal endRotation READ endRotation WRITE setEndRotation NOTIFY endRotationChanged) public: @@ -169,11 +169,11 @@ public: QPointF anchorPoint() const; void setAnchorPoint(const QPointF &point); - qreal orientationEntryInterval() const; - void setOrientationEntryInterval(qreal); + int orientationEntryDuration() const; + void setOrientationEntryDuration(int); - qreal orientationExitInterval() const; - void setOrientationExitInterval(qreal); + int orientationExitDuration() const; + void setOrientationExitDuration(int); qreal endRotation() const; void setEndRotation(qreal); @@ -191,8 +191,8 @@ Q_SIGNALS: void targetChanged(); void orientationChanged(Orientation); void anchorPointChanged(const QPointF &); - void orientationEntryIntervalChanged(qreal); - void orientationExitIntervalChanged(qreal); + void orientationEntryDurationChanged(qreal); + void orientationExitDurationChanged(qreal); void endRotationChanged(qreal); }; diff --git a/src/quick/items/qquickanimation_p_p.h b/src/quick/items/qquickanimation_p_p.h index 4a4f839..ee8125e 100644 --- a/src/quick/items/qquickanimation_p_p.h +++ b/src/quick/items/qquickanimation_p_p.h @@ -134,15 +134,15 @@ class QQuickPathAnimationPrivate : public QDeclarativeAbstractAnimationPrivate Q_DECLARE_PUBLIC(QQuickPathAnimation) public: QQuickPathAnimationPrivate() : path(0), target(0), - rangeIsSet(false), orientation(QQuickPathAnimation::Fixed), entryInterval(0), exitInterval(0), pa(0) {} + rangeIsSet(false), orientation(QQuickPathAnimation::Fixed), entryDuration(0), exitDuration(0), pa(0) {} QDeclarativePath *path; QQuickItem *target; bool rangeIsSet; QQuickPathAnimation::Orientation orientation; QPointF anchorPoint; - qreal entryInterval; - qreal exitInterval; + qreal entryDuration; + qreal exitDuration; QDeclarativeNullableValue endRotation; QDeclarativeBulkValueAnimator *pa; }; diff --git a/tests/auto/qtquick2/qdeclarativeanimations/data/pathAnimation2.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/pathAnimation2.qml index 951c5b2..2f64dac 100644 --- a/tests/auto/qtquick2/qdeclarativeanimations/data/pathAnimation2.qml +++ b/tests/auto/qtquick2/qdeclarativeanimations/data/pathAnimation2.qml @@ -15,8 +15,8 @@ Rectangle { target: redRect duration: 100; endRotation: 0 - orientationEntryInterval: .1 - orientationExitInterval: .1 + orientationEntryDuration: 10 + orientationExitDuration: 10 orientation: PathAnimation.RightFirst path: Path { startX: 50; startY: 50 -- 2.7.4