Author: billy
Copyright statement: The copyright belongs to the author, please contact the author for commercial reprinting, please indicate the source for non-commercial reprinting
Introduction
When using QML for interface development, our goal is to create a set of fluid interfaces,The so-called fluid interface refers to the UI components are dynamically changing. For example, when the components on the interface need to be changed, if the visual canvas changes suddenly, the user experience will be poor. And if we add some guidance in the process of state change, and slowly change the state from the initial state to the target state, so that the user can feel the process of change, then the user's sensory experience will be greatly improved, and this the so-called dynamic change
Several important concepts need to be drawn here:State, Transition, Animation
- State: All items have a default state that defines the default configuration of objects and property values. New states can be defined by adding state items to the states property to allow items to switch between different configurations
- Transition: The animation to apply when a state change occurs
- Animation: Gradually changing properties over time
For details, please refer to the official documentation: Important Concepts in Qt Quick - States, Transitions and Animations
Easing curve
Usually the changes in the animation are uniform. If the developer thinks it is too monotonous, the change speed curve of the animation can be adjusted, that is, the easing curve. We change the easing curve through the animation's easing property group
- type - the spiral type
- amplitude - amplitude
- period - the period
- overshoot - overshoot
- bezierCurve - Bezier
The types of spirals are as follows:
Spiral Type | image | illustrate |
---|---|---|
Easing.Linear | Easing curve for linear (t) function: velocity is constant (default) | |
Easing.InQuad | Easing curve for quadratic (t^2) function: acceleration from zero speed | |
Easing.OutQuad | Easing curve for quadratic (t^2) function: deceleration to zero speed | |
Easing.InOutQuad | Easing curve for quadratic (t^2) function: accelerate to half, then decelerate | |
Easing.OutInQuad | Easing curve for quadratic (t^2) function: slow down to half, then speed up | |
Easing.InCubic | Easing curve for cubic (t^3) function: acceleration from zero speed | |
Easing.OutCubic | Easing curve for cubic (t^3) function: decelerate to zero speed | |
Easing.InOutCubic | Easing curve for cubic (t^3) function: accelerate to half, then decelerate | |
Easing.OutInCubic | Easing curve for cubic (t^3) function: slow down to half, then speed up | |
Easing.InQuart | Easing curve for quartic (t^4) function: acceleration from zero speed | |
Easing.OutQuart | Easing curve for quartic (t^4) function: deceleration to zero speed | |
Easing.InOutQuart | Easing curve for a quartic (t^4) function: Accelerate to half, then decelerate | |
Easing.OutInQuart | Easing curve for a quartic (t^4) function: slow down to half, then speed up | |
Easing.InQuint | Easing curve for quintic (t^5) function: acceleration from zero speed | |
Easing.OutQuint | Easing curve for quintic (t^5) function: deceleration to zero speed | |
Easing.InOutQuint | Easing curve for a quintic (t^5) function: accelerate to half, then decelerate | |
Easing.OutInQuint | Easing curve for a quintic (t^5) function: slow down to half, then speed up | |
Easing.InSine | Easing curve of a sine function (sin(t)): acceleration from zero speed | |
Easing.OutSine | Easing curve for sine function (sin(t)): deceleration to zero speed | |
Easing.InOutSine | Easing curve for a sine function (sin(t)): Accelerate to half, then decelerate | |
Easing.OutInSine | Easing curve for a sine function (sin(t)): slow down to half, then speed up | |
Easing.InExpo | Easing curve for exponential (2^t) function: acceleration from zero speed | |
Easing.OutExpo | Easing curve for exponential (2^t) function: slow down to zero speed | |
Easing.InOutExpo | Easing curve for exponential (2^t) function: accelerate to half, then decelerate | |
Easing.OutInExpo | Easing curve for exponential (2^t) function: slow down to half, then speed up | |
Easing.InCirc | Easing curve for circular (sqrt(1-t^2)) function: acceleration from zero velocity | |
Easing.OutCirc | Easing curve for circular (sqrt(1-t^2)) function: decelerate to zero velocity | |
Easing.InOutCirc | Easing curve for circular (sqrt(1-t^2)) function: accelerate to half, then decelerate | |
Easing.OutInCirc | Easing curve for circular (sqrt(1-t^2)) function: slow down to half, then speed up | |
Easing.InElastic | Easing curve for elastic (exponentially decaying sine wave) function: acceleration from zero velocity. The peak amplitude can be set by the amplitude parameter, and the decay period can be set by the period parameter | |
Easing.OutElastic | Easing curve for elastic (exponentially decaying sine wave) function: slow down to zero velocity. The peak amplitude can be set by the amplitude parameter, and the decay period can be set by the period parameter | |
Easing.InOutElastic | Easing curve for elastic (exponentially decaying sine wave) function: accelerate to half, then decelerate | |
Easing.OutInElastic | Easing curve for elastic (exponentially decaying sine wave) function: slow down to half, then speed up | |
Easing.InBack | Easing curve for backward (overshoot cubic function: (s+1)*t 3-s*t 2) function: acceleration from zero speed | |
Easing.OutBack | Easing curve for backward (overshoot cubic function: (s+1)*t 3-s*t 2) function: decelerate to zero speed | |
Easing.InOutBack | Easing curve for backward (overshoot cubic function: (s+1)*t 3-s*t 2) function: accelerate to half, then decelerate | |
Easing.OutInBack | Easing curve for the back (overshoot cubic function: (s+1)*t 3-s*t 2) function: decelerate to half, then accelerate | |
Easing.InBounce | Easing curve for bounce (exponential decay parabolic bounce) function: acceleration from zero velocity | |
Easing.OutBounce | Easing curve for bounce (exponential decay parabolic bounce) function: slow down to zero velocity | |
Easing.InOutBounce | Easing curve for bounce (exponential decay parabolic bounce) function: accelerate to half, then decelerate | |
Easing.OutInBounce | Easing curve for the bounce (exponential decay parabolic bounce) function: slow down to half, then speed up | |
Easing.Bezier | - | A custom easing curve defined by the easing.beziercrove property |
type of animation
- AnchorAnimation - Animate changes to anchor values
Rectangle {
id: myRect
width: 100; height: 100
color: "red"
property int type: 1
states: [
State {
name: "right"
AnchorChanges { target: myRect; anchors.right: parent.right }
},
State {
name: "bottom"
AnchorChanges { target: myRect; anchors.bottom: parent.bottom }
},
State {
name: "left"
AnchorChanges { target: myRect; anchors.left: parent.left }
},
State {
name: "top"
AnchorChanges { target: myRect; anchors.top: parent.top }
}
]
transitions: Transition {
AnchorAnimation { duration: 500 }
}
MouseArea {
anchors.fill: parent
onClicked: {
let state = {
1: "right",
2: "bottom",
3: "left",
4: "top"
}
myRect.state = state[myRect.type]
myRect.type++
if ( myRect.type > 4 ) {
myRect.type = 1
}
}
}
}
- ColorAnimation - Animate changes in color values
Rectangle {
id: myRect
width: 100; height: 100
color: "black"
property int type: 1
states: [
State {
name: "red"
PropertyChanges { target: myRect; color: "red" }
},
State {
name: "yellow"
PropertyChanges { target: myRect; color: "yellow" }
},
State {
name: "pink"
PropertyChanges { target: myRect; color: "pink" }
},
State {
name: "blue"
PropertyChanges { target: myRect; color: "blue" }
},
State {
name: "black"
PropertyChanges { target: myRect; color: "black" }
}
]
transitions: Transition {
ColorAnimation { duration: 500 }
}
MouseArea {
anchors.fill: parent
onClicked: {
let state = {
1: "red",
2: "yellow",
3: "pink",
4: "blue",
5: "black",
}
myRect.state = state[myRect.type]
myRect.type++
if ( myRect.type > 5 ) {
myRect.type = 1
}
}
}
}
- NumberAnimation - Animate changes to a value of type qreal
Rectangle {
id: myRect
width: 100; height: 100
color: "red"
property int type: 1
states: [
State {
name: "step1"
PropertyChanges { target: myRect; x: 60; y: 60; width: 120; height: 120; rotation: 30 }
},
State {
name: "step2"
PropertyChanges { target: myRect; x: 60; y: 60; width: 120; height: 120; rotation: 60 }
},
State {
name: "step3"
PropertyChanges { target: myRect; x: 40; y: 40; width: 180; height: 180; rotation: 90 }
},
State {
name: "step4"
PropertyChanges { target: myRect; x: 100; y: 100; width: 50; height: 50; rotation: 45 }
}
]
transitions: Transition {
NumberAnimation { duration: 500 }
}
MouseArea {
anchors.fill: parent
onClicked: {
let state = {
1: "step1",
2: "step2",
3: "step3",
4: "step4"
}
myRect.state = state[myRect.type]
myRect.type++
if ( myRect.type > 4 ) {
myRect.type = 1
}
}
}
}
- ParentAnimation - Animate changes to the parent class
Rectangle {
id: myRect
width: 300; height: 100
color: "black"
property int type: 1
Rectangle {
id: redRect
width: 100; height: 100
color: "red"
}
Rectangle {
id: blueRect
x: 110
width: 100; height: 100
color: "blue"
}
Rectangle {
id: yellowRect
x: 220; y: 10
width: 50; height: 50
color: "yellow"
states: [
State {
name: "red"
ParentChange { target: yellowRect; parent: redRect; x: 10; y: 10 }
},
State {
name: "blue"
ParentChange { target: yellowRect; parent: blueRect; x: 10; y: 10 }
},
State {
name: "black"
ParentChange { target: yellowRect; parent: myRect; x: 220; y: 10 }
}
]
transitions: Transition {
ParentAnimation {
NumberAnimation { properties: "x,y"; duration: 500 }
}
}
MouseArea {
anchors.fill: parent
onClicked: {
let state = {
1: "red",
2: "blue",
3: "black"
}
yellowRect.state = state[myRect.type]
myRect.type++
if ( myRect.type > 3 ) {
myRect.type = 1
}
}
}
}
}
- PathAnimation - Animate an item along a path
Rectangle {
width: 400; height: 400
PathInterpolator {
id: motionPath
path: Path {
startX: 0; startY: 0
PathCubic {
x: 350; y: 350
control1X: 350; control1Y: 0
control2X: 0; control2Y: 350
}
}
NumberAnimation on progress { id: animation; from: 0; to: 1; duration: 2000 }
}
Rectangle {
x: motionPath.x; y: motionPath.y
width: 50; height: 50
rotation: motionPath.angle
color: "green"
}
MouseArea {
anchors.fill: parent
onClicked: animation.start()
}
}
- PropertyAnimation - Animate changes to property values
Rectangle {
width: 100; height: 100
color: "red"
property bool location: true
Behavior on x { PropertyAnimation {} }
MouseArea {
anchors.fill: parent
onClicked: {
var x = location ? 50 : 0
parent.x = x
location = !location
}
}
}
- RotationAnimation - Animate changes in rotation
Item {
width: 300; height: 300
Rectangle {
id: myRect
width: 150; height: 100
anchors.centerIn: parent
color: "red"
antialiasing: true
property int type: 1
states: [
State {
name: "state1"
PropertyChanges { target: myRect; rotation: 45 }
},
State {
name: "state2"
PropertyChanges { target: myRect; rotation: 90 }
},
State {
name: "state3"
PropertyChanges { target: myRect; rotation: 180 }
}
]
transitions: Transition {
RotationAnimation { duration: 1000; direction: RotationAnimation.Counterclockwise }
}
}
MouseArea {
anchors.fill: parent
onClicked: {
let state = {
1: "state1",
2: "state2",
3: "state3"
}
myRect.state = state[myRect.type]
myRect.type++
if ( myRect.type > 3 ) {
myRect.type = 1
}
}
}
}
- Vector3dAnimation - Animate changes to QVector3d values
Rectangle {
id: myRect
x: 50; y: 50
width: 100; height: 100
color: "red"
transform: Rotation {
angle: 45
origin.x: 50; origin.y: 50
axis: Qt.vector3d(0, 1, 0)
SequentialAnimation on axis {
id: animation
running: false
Vector3dAnimation { from: "1, 0, 0"; to: "0, 1, 0"; duration: 1000 }
Vector3dAnimation { from: "0, 1, 0"; to: "0, 0, 1"; duration: 1000 }
Vector3dAnimation { from: "0, 0, 1"; to: "1, 0, 1"; duration: 1000 }
Vector3dAnimation { from: "1, 0, 1"; to: "1, 1, 0"; duration: 1000 }
Vector3dAnimation { from: "1, 1, 0"; to: "1, 1, 1"; duration: 1000 }
Vector3dAnimation { from: "1, 1, 1"; to: "1, 0, 1"; duration: 1000 }
Vector3dAnimation { from: "1, 0, 1"; to: "0, 0, 1"; duration: 1000 }
Vector3dAnimation { from: "0, 0, 1"; to: "0, 1, 0"; duration: 1000 }
Vector3dAnimation { from: "0, 1, 0"; to: "1, 0, 0"; duration: 1000 }
}
}
MouseArea {
anchors.fill: parent
onClicked: animation.start()
}
}
Combine animation
- SequentialAnimation - run animations sequentially
Rectangle {
id: rect
width: 100; height: 100
color: "red"
SequentialAnimation {
id: animation
running: false
NumberAnimation { target: rect; property: "x"; to: 100; duration: 500 }
NumberAnimation { target: rect; property: "y"; to: 100; duration: 500 }
NumberAnimation { target: rect; property: "x"; to: 0; duration: 500 }
NumberAnimation { target: rect; property: "y"; to: 0; duration: 500 }
}
MouseArea {
anchors.fill: parent
onClicked: animation.start()
}
}
- ParallelAnimation - Run animations in parallel
Rectangle {
id: rect
width: 100; height: 100
color: "red"
ParallelAnimation {
id: animation
running: false
NumberAnimation { target: rect; property: "x"; to: 100; duration: 1000 }
NumberAnimation { target: rect; property: "y"; to: 100; duration: 1000 }
NumberAnimation { target: rect; property: "width"; to: 200; duration: 1000 }
NumberAnimation { target: rect; property: "height"; to: 200; duration: 1000 }
NumberAnimation { target: rect; property: "rotation"; to: 90; duration: 1000 }
}
MouseArea {
anchors.fill: parent
onClicked: animation.start()
}
}
behavior animation
- Behavior - Specifies the default animation for property changes
Rectangle {
id: coloredRect
width: 100; height: 100
anchors.centerIn: parent
color: "red"
states: State {
name: "GreenState"
when: mouser.containsMouse
PropertyChanges {
target: coloredRect
color: "green"
}
}
Behavior on color { ColorAnimation {} }
MouseArea {
id: mouser
anchors.fill: parent
hoverEnabled: true
}
}
animation paused
- PauseAnimation - Introduce a pause in the animation
Rectangle {
id: rect
width: 100; height: 100
color: "red"
SequentialAnimation {
id: animation
running: false
NumberAnimation { target: rect; property: "x"; to: 100; duration: 500 }
NumberAnimation { target: rect; property: "y"; to: 100; duration: 500 }
PauseAnimation { duration: 1000 }
NumberAnimation { target: rect; property: "x"; to: 0; duration: 500 }
NumberAnimation { target: rect; property: "y"; to: 0; duration: 500 }
}
MouseArea {
anchors.fill: parent
onClicked: animation.start()
}
}
spring animation
- SpringAnimation - Simulates the oscillating behavior of a spring, using appropriate spring constants to control acceleration and damping to control how quickly the effect fades away
Rectangle {
id: rect
width: 50; height: 50
color: "red"
Behavior on x { SpringAnimation { spring: 2; damping: 0.2 } }
Behavior on y { SpringAnimation { spring: 2; damping: 0.2 } }
MouseArea {
anchors.fill: parent
onClicked: {
rect.x = mouse.x - rect.width/2
rect.y = mouse.y - rect.height/2
}
}
}
property tracking animation
- SmoothedAnimation - Allows features to smooth track values
Item {
Rectangle {
width: 60; height: 60
x: rect1.x - 5; y: rect1.y - 5
color: "green"
Behavior on x { SmoothedAnimation { velocity: 200; duration: 500 } }
Behavior on y { SmoothedAnimation { velocity: 200; duration: 500 } }
}
Rectangle {
id: rect1
x: 5; y: 5
width: 50; height: 50
color: "red"
}
focus: true
Keys.onRightPressed: rect1.x = rect1.x + 100
Keys.onLeftPressed: rect1.x = rect1.x - 100
Keys.onUpPressed: rect1.y = rect1.y - 100
Keys.onDownPressed: rect1.y = rect1.y + 100
}
Run script in animation
- ScriptAction - run script in animation
Rectangle {
id: rect
width: 100; height: 100
color: "red"
SequentialAnimation {
id: animation
running: false
NumberAnimation { target: rect; property: "x"; to: 100; duration: 500 }
NumberAnimation { target: rect; property: "y"; to: 100; duration: 500 }
ScriptAction { script: doSomething() }
NumberAnimation { target: rect; property: "x"; to: 0; duration: 500 }
NumberAnimation { target: rect; property: "y"; to: 0; duration: 500 }
ScriptAction { script: doStateStuff() }
}
MouseArea {
anchors.fill: parent
onClicked: animation.start()
}
function doSomething() {
rect.color = "blue"
rect.width = 120
rect.height = 120
}
function doStateStuff() {
rect.color = "red"
rect.width = 100
rect.height = 100
}
}