26.Qt Quick QML-RotationAnimation、PathAnimation、SmoothedAnimation、Behavior、PauseAnimation、SequentialAnimation和ParallelAnimation

諾謙發表於2021-06-05

1.RotationAnimation
RotationAnimation也是繼承於PropertyAnimation元件,但是它有點特殊,它只需要指定taget目標物件,並且不需要指定property,因為rotation就是要繫結的屬性.並且它還多了個direction屬性:

  • direction : enumeration,設定旋轉的方向,取值有:
    • RotationAnimation.Numerical (預設值) - 數值旋轉,通過to-from得出要旋轉的度數,然後進行旋轉,比如from為10,to為100,那麼旋轉就是90°
    • RotationAnimation.Clockwise - 在兩個度數之間進行順時針旋轉,比如from為10,to為100,那麼順旋轉就是90°
    • RotationAnimation.Counterclockwise - 在兩個度數之間進行逆時針旋轉,比如from為10,to為100,那麼逆旋轉就是90°
    • RotationAnimation.Shortest - 沿最短路徑的方向旋轉。比如from為10,to為350,那麼將逆時針旋轉20°

示例如下所示:

  property var rotationModel: [
        ["#00FF00", RotationAnimation.Numerical],
        ["#FF0000", RotationAnimation.Clockwise],
        ["#0000FF", RotationAnimation.Counterclockwise],
        ["#00FFFF", RotationAnimation.Shortest],
    ]
    property var animations: new Array(0)

    MouseArea {
        id: area
        anchors.fill: parent
        onPressed: {
            for (var i in animations) {
                console.log(animations[i].direction)
                animations[i].start();
            }
        }
    }

    Row {
        spacing: 10
        Repeater {
            model: rotationModel.length
            Rectangle {
                id: rect
                width: 100
                height: 100
                radius: width / 2
                color: rotationModel[index][0]
                Text {
                    anchors.centerIn: parent
                    text: "model"+ index.toString()
                    color: "white"
                    font.pixelSize: 18
                    font.bold: true
                }
                RotationAnimation {
                    running: true
                    duration: 500
                    target: rect
                    direction: rotationModel[index][1]
                    from :  10
                    to :  350
                    Component.onCompleted: animations[index] = this
                }
            }
        }
    }

效果如下所示:

 

2.PathAnimation
PathAnimation繼承於Animation元件,用來實現一個路徑動畫.

它的屬性如下所示:

  • anchorPoint : point,設定目標瞄點,預設為目標的左上角(其0,0點)將定位到(或跟隨)路徑。比如10x10的Rectangle,那麼anchorPoint為Qt.point(5, 5)時則表示始終讓物體中心處於路徑上
  • duration : int,持續時間
  • easing.type : enumeration,設定動畫的緩和曲線.預設值為Easing.Linear(線性過程),比如我們設定為Easing.InQuad時,動畫效果就是從慢到快的過程.
  • easing.amplitude : real,設定緩和曲線的振幅,預設值為1.0,值越大振幅越大,僅當easing.type為Easing.InBounce, Easing.OutBounce, Easing.InOutBounce, Easing.OutInBounce, Easing.InElastic, Easing.OutElastic, Easing.InOutElastic or Easing.OutInElastic才生效
  • orientation : enumeration,設定物件在路徑上的方向,取值有以下幾種:
    • PathAnimation.Fixed (default) - 在動畫中只是移動物體,並不旋轉物體
    • PathAnimation.RightFirst - 始終讓目標的右側在前面沿著路徑移動
    • PathAnimation.LeftFirst - 始終讓目標的左側在前面沿著路徑移動
    • PathAnimation.BottomFirst - 始終讓目標的底部在前面沿著路徑移動
    • PathAnimation.TopFirst - 始終讓目標的頂部在前面沿著路徑移動
  • endRotation : real,設定目標移動路徑結束後的旋轉角度,如果orientationEntryDuration未設定,物體則會直接跳轉到該值,否則就以動畫的形式結束
  • orientationEntryDuration : real,設定啟動時的旋轉過渡時間(毫秒單位),比如啟動動畫時,如果當前目標方向和orientation值方向不一致,則需要一個過渡時間才行
  • orientationExitDuration : real,設定結束時的旋轉過渡時間(毫秒單位),如果endRotation已設定,那麼就會有個過渡時間,讓物體最終旋轉到endRotation角度.
  • target : Item ,設定動畫的目標物件
  • path : Path,設定動畫的路徑。

接下來我們便來講解Path路徑

3.Path
一個Path可以由下面多個Path段組成:

  • PathLine : 由一個座標指定的直線路徑
  • PathPolyline : 由一個path座標列表指定的多段路徑
  • PathQuad : 由一個控制點生成的二次貝塞爾曲線路徑
  • PathCubic : 由兩個控制點生成的三次貝塞爾曲線路徑
  • PathArc : 由結束座標,以及一個radiusX和radiusY半徑實現的一個圓弧(順時針繪畫)
  • PathAngleArc : 由中心點、半徑和起始角度startAngle、旋轉角度sweepAngle指定的圓弧。
  • PathCurve :由一個座標點生成的curve曲線路徑(通常需要配合多個PathCurve才行)
  • PathSvg : 由SVG路徑字串實現的路徑。你可以用它建立線條, 曲線, 弧形等等

顯示一個Path路徑
我們可以通過設定context2D的path屬性,來顯示出我們繪畫的Path路徑,不然都不知道繪製的路徑到底對不對,真是"半夜吃黃瓜-摸不著頭尾"
我們以PathArc為例,示例如下所示:

Canvas {
            id: canvas
            anchors.fill: parent
            antialiasing: true

            onPaint: {
                var context = canvas.getContext("2d")
                context.clearRect(0, 0, width, height)
                context.strokeStyle = "black"
                context.path = path
                context.stroke()
            }
        }

        Path {
            id: path
            startX: 100; startY: 100

            PathArc {
              x: 100; y: 140
              radiusX: 100; radiusY: 50
              useLargeArc: true
              xAxisRotation: 30
            }
}

效果如下所示:

 

這裡我們設定弧線的起始位置為(100,100),終點位置為(100,140).
它的useLargeArc為true,表示使用角度大的那個圓弧,如果設定為false,則將會使用小的那個圓弧
它的xAxisRotation表示x水平方向是否傾斜,我們這裡按順時針傾斜了30°,該值僅在x和y半徑不同時有用,這意味著圓弧是橢圓形的

接下來我們便來學習PathSvg路徑.
4.PathSvg
PathSvg支援的命令如下所示:

  • M = moveto,移動畫筆到指定點處(只是移動位置,不畫線),寫法:M x y
  • L = lineto,從當前點繪製一條直線到目的點,寫法:L x y
  • H = horizontal lineto,繪製一條平行線,寫法:H x
  • V = vertical lineto,繪製一條垂直線,寫法:V y
  • C = curveto,繪製一條三次貝塞爾曲線,寫法:C x1 y1, x2 y2, x y (x和y為終點,其它兩個為控制點)
  • S = smooth curveto,用來寫在C命令後面時來延長貝塞爾曲線,當然也可以跟在S命令後面,寫法:S x1 y1, x y(x1和y1是控制點,x和y是終點)
  • Q = quadratic Bézier curve,繪製一條二次貝塞爾曲線,寫法:Q x1 y1, x y
  • T = smooth quadratic Bézier curveto,用來寫在Q命令後面時來延長貝塞爾曲線,當然也可以跟在T命令後面,寫法:T x y
  • A = elliptical Arc,繪製一條圓弧,寫法:A rx ry x-axis-rotation large-arc-flag sweep-flag x y
    • rx、ry:表示圓弧的半徑
    • x-axis-rotation: 表示x水平方向是否傾斜,比如設定為-45,則圓弧會逆時針傾斜45°,注意:該值僅在x和y半徑不同時有用,這意味著圓弧是橢圓形的
    • large-arc-flag:設定為0表示繪製小圓弧,為1表示大圓弧
    • sweep-flag: 表示弧線的方向,0表示從起點到終點沿逆時針畫弧,1表示從起點到終點沿順時針畫弧
    • x、y:表示繪製的終點位置
  • Z = closepath,關閉路徑,將會從當前點繪製一條直線到開始點.

5.PathAnimation使用PathSvg示例

Canvas {
            id: canvas
            anchors.fill: parent
            antialiasing: true
            onPaint: {
                var context = getContext("2d")
                context.clearRect(0, 0, width, height)
                context.strokeStyle = "red"
                context.path = pathAnim.path
                context.stroke()
            }
    }

    PathAnimation {
        id: pathAnim
        running: true
        loops: Animation.Infinite
        duration: 5000
        easing.type: Easing.InQuad
        target: car
        orientation: PathAnimation.RightFirst
        anchorPoint: Qt.point(car.width/2, car.height)
        path: Path {
            startX: 100; startY: 100

            PathSvg {
               path: "M100 100 C600 50, 50 300, 550 250"
            }
        }
    }

    Item {
        id: car
        x: 25; y: 25
        width: 80; height: 38

        Canvas {
            id: canvas2
            anchors.fill: parent
            antialiasing: true
            onPaint: {
                var context = getContext("2d")
                context.clearRect(0, 0, width, height)
                context.fillStyle = "blue"
                context.fillRect(0,0,width,height-10)

                context.fillStyle = "yellow"
                context.ellipse(10,height-20,20,20)

                context.ellipse(width-30,height-20,20,20)
                context.fill()
                console.log(width,height)
            }
        }

        Text {
            anchors.centerIn: parent
            text: "小車"
            color: "white"
        }
    }

效果如下所示:

 

6.SmoothedAnimation
SmoothedAnimation繼承於NumberAnimation元件,它比NumberAnimation更加人性化,不僅可以設定duration時間,還可以設定滑動速率。
並且SmoothedAnimation的easing.type預設值為Easing.InOutQuad(慢->快->慢).
SmoothedAnimation如果同時指定了velocity速度和duration持續時間,則會選擇導致動畫速度最快的那個所需時間.
例如:

  • 如果velocity速度設定為200,如果duration設定為5000.
  • 假如此時需要將一個物體從0位移到800,那麼此時將會選擇velocity速度的時間,因為只需要4秒時間.
  • 假如此時需要將一個物體從0位移到2000,那麼此時將會選擇duration時間,因為只需要5秒時間.

它的屬性如下所示:

  • duration : int,持續時間,預設值為-1.表示禁用持續時間值。
  • reversingMode : enumeration,設定如果動畫方向被突然被反轉後的行為(比如當前動畫正在往左邊移動時,突然使用者讓動畫往右邊移動),取值如下所示:
  • SmoothedAnimation.Eased(預設)-動畫將按照速度平滑減速到0後,開始反轉方向加速
  • SmoothedAnimation.Immediate-動畫將立即以0的速度開始反向加速
  • SmoothedAnimation.Sync-立即將屬性設定為目標值
  • velocity : real,設定速度,預設值為200(200畫素點每秒),如果將此設定為-1(預設值)將禁用速度值。

示例如下所示:

    MouseArea {
            anchors.fill: parent
            hoverEnabled: true
            onPositionChanged: {

                animation1.to = mouseX - rect.width/2
                animation2.to = mouseY - rect.height/2
                animation1.restart()
                animation2.restart()
            }
        }

    Rectangle {
        id: rect
        color: "red"
        width: 60; height: 60
        radius: width/2

        SmoothedAnimation on x{
            id: animation1
            velocity: 100
            reversingMode: SmoothedAnimation.Immediate
        }
        SmoothedAnimation on y{
            id: animation2
            velocity: 100
            reversingMode: SmoothedAnimation.Immediate
        }

    }

只要當我們滑鼠位置發生改變就會啟動SmoothedAnimation動畫進行平滑移動,但是我們這樣寫,程式碼顯得有點繁瑣,可以使用Behavior元件來代替設定from和to的行為來節省程式碼量
接下來我們來給大家講講Behavior.


7.Behavior
Behavior用來讓動畫繫結到物件一個屬性上,Behavior中文翻譯就是行為的意思,所以當繫結屬性發生改變時,就會自動觸發Behavior行為,Behavior就會自動設定動畫的to屬性,並啟動動畫.
Behavior只有兩個屬性animation和enabled, animation儲存著要觸發行為的哪個動畫,enabled表示是否使能行為,預設為true.
Behavior示例如下所示:

MouseArea {
        anchors.fill: parent
        hoverEnabled: true
        onPositionChanged: {
            rect.x = mouseX - rect.width/2
            rect.y = mouseY - rect.height/2
        }
    }

Rectangle {
    id: rect
    color: "red"
    width: 60; height: 60
    radius: width/2

    Behavior on x {
        SmoothedAnimation {
            velocity: 100
            reversingMode: SmoothedAnimation.Immediate
        }
    }
    Behavior on y {
        SmoothedAnimation {
            velocity: 100
            reversingMode: SmoothedAnimation.Immediate
        }
    }

}

這裡我們使用Behavior分別為屬性繫結了SmoothedAnimation動畫,然後我們只需要改變x,y屬性,就會自動觸發行為,設定我們改變的值到動畫的to屬性中,並啟動動畫

 

8.PauseAnimation
PauseAnimation顧名思義就是暫停動畫的意思,只有一個duration屬性,用來設定該期間內什麼都不做.
並且只能在SequentialAnimation動畫中使用,接下來我們便來學習SequentialAnimation和ParallelAnimation,並在程式碼中使用它


9.SequentialAnimation和ParallelAnimation
SequentialAnimation用來將多個動畫序列地執行下去.而ParallelAnimation是用來將多個動畫並行地執行下去.
並且SequentialAnimation和ParallelAnimation還可以互相巢狀.
需要注意的是:

  • SequentialAnimation或ParallelAnimation中定義的動畫不能單獨啟動和停止;必須作為一個組來啟動和停止。
  • 並且SequentialAnimation和ParallelAnimation的running預設為false.如果要想載入元件後立即啟動的話,我們需要手動設定(不需要全部設定,只需要設定最頂層動畫的running值即可)

示例如下所示:

Window{
    id: window
    width: 480
    height: 320
    visible: true

    SequentialAnimation {
        SequentialAnimation {
            ParallelAnimation {
                NumberAnimation {
                    target: ball1
                    property: "y"
                    from: 20
                    to: height - ball1.height - 20
                    easing.type: Easing.OutBounce;
                    duration: 1200
                }
                NumberAnimation {
                    target: ball2
                    property: "y"
                    from: 20
                    to: height - ball2.height - 20
                    easing.type: Easing.OutBounce;
                    duration: 800
                }
            }
        }
        PauseAnimation { duration: 500 }
        running: true
        loops: Animation.Infinite
    }

    Rectangle {
        id: ball1
        width: 40; height: 40;
        radius: 20
        color: "blue"
        x: 30
    }
    Rectangle {
        id: ball2
        width: 60; height: 60;
        radius: 30
        color: "red"
        x: 200
    }
}

效果如下所示:

如上圖所示,可以看到每當小球落到地後,就會啟動PauseAnimation暫停動畫,等待500ms

 

相關文章