How to draw Windows 10 startup animation
-
@jsulm Thank you. I know I can do that, but I want to make a component that can change the color or change the size
@zybzyb Then you can use https://doc.qt.io/qt-5/animation-overview.html and https://doc.qt.io/qt-6/qpainter.html
-
@zybzyb Then you can use https://doc.qt.io/qt-5/animation-overview.html and https://doc.qt.io/qt-6/qpainter.html
-
@zybzyb Hi
The angular velocity equation for a constant velocity should be a parametric equation like this
x(t) = Amplitude * cos( 2 * pi * f * t + o)
y(t) = Amplitude * sin( 2 * pi * f * t + o)
where Amplitude is the radius, f is the frequency and o is phase or offset angle value to decide where the angle should start.
You should replace Amplitude, frequency and o with "sane" values.
Since the velocity is not constant, you need to change the frequency from a static value to a dinamic value that changes with the position, where the formulas will change to some thing like:x(t) = Amplitude * cos( abs( 2 * pi * cos(t) ) + o)
y(t) = Amplitude * sin( abs( 2 * pi * cos(t) ) + o)Note that this is formula for one dot, you will need to draw several dots, where the phase o needs to be differente for each dot, they need to be spaced.
Right now I dont have time to test this formulas, maybe later I will try to do a demo.Edit (ok, my previous answer was wrong)
So far I have come up with this, which is not what you want but is getting closer, I will come back later when possible. So far it has only two dots, needs more dots and to fix velocity and spacing.
Item { id: root width: 400 height: 400 property real midleX: root.width * 0.5 property real midleY: root.height * 0.5 property real amp: root.width * 0.3 property real t: 0 property real i: 0 Rectangle { id: dot1 width: 10 height: width radius: width * 0.5 color: "blue" x: midleX + amp * Math.cos( i ) y: midleY + amp * Math.sin( i ) } Rectangle { id: dot2 width: 10 height: width radius: width * 0.5 color: "red" x: midleX + amp * Math.cos( t + Math.abs( 1.2* Math.cos(t*0.5 + Math.PI / 20 )) + Math.PI / 10) y: midleY + amp * Math.sin( t + Math.abs( 1.2* Math.cos(t*0.5 + Math.PI / 20 )) + Math.PI / 10) } MouseArea { anchors.fill: parent onClicked: { t = 0 i = 0 timmer.running = true } } Timer { id: timmer interval: 16 running: false repeat: true onTriggered: { //var delta = 0.5 * Math.abs(Math.cos(t)) //i = i + 0.2 i = t + Math.abs( 1.2* Math.cos(t*0.5)) t = t + 0.04 if (i > (20 * Math.PI ) ) running = false console.log("t: " + t) console.log("0.3 * Math.abs(Math.cos(t)):" + 0.3 * Math.abs(Math.cos(t)) ) // update() } } }
-
@zybzyb Hi
The angular velocity equation for a constant velocity should be a parametric equation like this
x(t) = Amplitude * cos( 2 * pi * f * t + o)
y(t) = Amplitude * sin( 2 * pi * f * t + o)
where Amplitude is the radius, f is the frequency and o is phase or offset angle value to decide where the angle should start.
You should replace Amplitude, frequency and o with "sane" values.
Since the velocity is not constant, you need to change the frequency from a static value to a dinamic value that changes with the position, where the formulas will change to some thing like:x(t) = Amplitude * cos( abs( 2 * pi * cos(t) ) + o)
y(t) = Amplitude * sin( abs( 2 * pi * cos(t) ) + o)Note that this is formula for one dot, you will need to draw several dots, where the phase o needs to be differente for each dot, they need to be spaced.
Right now I dont have time to test this formulas, maybe later I will try to do a demo.Edit (ok, my previous answer was wrong)
So far I have come up with this, which is not what you want but is getting closer, I will come back later when possible. So far it has only two dots, needs more dots and to fix velocity and spacing.
Item { id: root width: 400 height: 400 property real midleX: root.width * 0.5 property real midleY: root.height * 0.5 property real amp: root.width * 0.3 property real t: 0 property real i: 0 Rectangle { id: dot1 width: 10 height: width radius: width * 0.5 color: "blue" x: midleX + amp * Math.cos( i ) y: midleY + amp * Math.sin( i ) } Rectangle { id: dot2 width: 10 height: width radius: width * 0.5 color: "red" x: midleX + amp * Math.cos( t + Math.abs( 1.2* Math.cos(t*0.5 + Math.PI / 20 )) + Math.PI / 10) y: midleY + amp * Math.sin( t + Math.abs( 1.2* Math.cos(t*0.5 + Math.PI / 20 )) + Math.PI / 10) } MouseArea { anchors.fill: parent onClicked: { t = 0 i = 0 timmer.running = true } } Timer { id: timmer interval: 16 running: false repeat: true onTriggered: { //var delta = 0.5 * Math.abs(Math.cos(t)) //i = i + 0.2 i = t + Math.abs( 1.2* Math.cos(t*0.5)) t = t + 0.04 if (i > (20 * Math.PI ) ) running = false console.log("t: " + t) console.log("0.3 * Math.abs(Math.cos(t)):" + 0.3 * Math.abs(Math.cos(t)) ) // update() } } }
@johngod I want to join the "challenge" :D
I tried to simply split the animation into parts and use QML animations to re-create it.
Here is an example of my approach (in order to match the animation exactly, it could use some tweaking as well):
// WindowsSpinner.qml Rectangle { id: container implicitWidth: 200 implicitHeight: 200 color: "transparent" property int dotCount: 5 property int dotSize: 20 property color dotColor: "black" property int loopDuration: 3500 Repeater { model: dotCount Rectangle { id: dot width: dotSize height: dotSize radius: dotSize / 2 color: dotColor opacity: 0 x: container.width / 2 - dotSize / 2 y: container.height - dotSize SequentialAnimation { loops: 1 running: true // let each dot start with increasing delay PauseAnimation { duration: index * loopDuration / dotCount / dotCount } SequentialAnimation { loops: Animation.Infinite NumberAnimation { target: dot property: "opacity" from: 0 to: 1 duration: 0 } NumberAnimation { target: rotationTransform property: "angle" from: 0 to: 180 duration: loopDuration * 0.25 easing.type: Easing.Linear } NumberAnimation { target: rotationTransform property: "angle" from: 180 to: 450 duration: loopDuration * 0.15 easing.type: Easing.Linear } NumberAnimation { target: rotationTransform property: "angle" from: 450 to: 720 duration: loopDuration * 0.35 easing.type: Easing.Linear } NumberAnimation { target: dot property: "opacity" from: 1 to: 0 duration: 0 } PauseAnimation { duration: loopDuration * 0.25 } } } // set rotation origin point for animations transform: Rotation { id: rotationTransform origin.x: container.width / 2 - dot.x origin.y: container.height / 2 - dot.y axis { x: 0 y: 0 z: 1 } } } } }
// main.qml Window { id: root width: 640 height: 480 visible: true WindowsSpinner { anchors.centerIn: parent dotSize: height / 8 dotColor: "teal" } }