feat: improve loading indicator
This commit is contained in:
parent
3b1dd828f5
commit
000c9a459b
1 changed files with 68 additions and 30 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
import QtQuick
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
import M3Shapes
|
import M3Shapes
|
||||||
import Caelestia.Config
|
import Caelestia.Config
|
||||||
import qs.components
|
import qs.components
|
||||||
|
|
@ -15,50 +16,87 @@ MaterialShape {
|
||||||
property int shapeIndex
|
property int shapeIndex
|
||||||
property real cRotation
|
property real cRotation
|
||||||
property real lRotation
|
property real lRotation
|
||||||
|
property real thisLRotation
|
||||||
property bool containsIcon
|
property bool containsIcon
|
||||||
|
|
||||||
property bool animated: true
|
property bool animated: true
|
||||||
property int morphAnimRotation: 60
|
property int morphAnimRotation: 60
|
||||||
property alias morphAnimDelay: morphAnimDelay.duration
|
property real morphScale: 0.14
|
||||||
property alias rotateAnimDuration: rotateAnim.duration
|
property alias rotateAnimDuration: rotateAnim.duration
|
||||||
|
|
||||||
readonly property easingCurve scaleCurve: [0.00, 0.56, 0.55, 1.29, 1, 1]
|
property real stiffness: 180
|
||||||
|
property real dampingRatio: 0.6
|
||||||
|
property real visibilityThreshold: 0.075
|
||||||
|
|
||||||
implicitSize: 38
|
readonly property real springDuration: {
|
||||||
rotation: cRotation + lRotation
|
const wn = Math.sqrt(stiffness);
|
||||||
|
const r = -dampingRatio * wn;
|
||||||
|
const c = 1 / Math.sqrt(1 - dampingRatio * dampingRatio);
|
||||||
|
return Math.log(visibilityThreshold / c) / r;
|
||||||
|
}
|
||||||
|
readonly property real springMaxVelocity: {
|
||||||
|
const wn = Math.sqrt(stiffness);
|
||||||
|
const factor = Math.exp(-z * Math.acos(z) / Math.sqrt(1 - z * z));
|
||||||
|
return wn * factor;
|
||||||
|
}
|
||||||
|
property bool springSettled: true
|
||||||
|
|
||||||
shape: shapes[shapeIndex]
|
function spring(t: real): var {
|
||||||
color: Colours.palette.m3primary
|
const wn = Math.sqrt(stiffness);
|
||||||
|
const za = dampingRatio * wn;
|
||||||
|
|
||||||
animationDuration: Tokens.anim.durations.expressiveSlowSpatial
|
const wd = wn * Math.sqrt(1 - dampingRatio * dampingRatio);
|
||||||
animationEasing: Tokens.anim.expressiveSlowSpatial
|
const r = za / wd;
|
||||||
|
const pos = 1 - Math.exp(-za * t) * (Math.cos(wd * t) + r * Math.sin(wd * t));
|
||||||
|
const vel = Math.exp(-za * t) * (wn * wn / wd) * Math.sin(wd * t);
|
||||||
|
|
||||||
scale: {
|
return [pos, vel];
|
||||||
const t = scaleCurve.valueForProgress(morphProgress);
|
|
||||||
return 1 + 0.15 * Math.sin(t * Math.PI) / 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SequentialAnimation {
|
implicitSize: 38
|
||||||
|
color: Colours.palette.m3primary
|
||||||
|
toShape: shapes[0]
|
||||||
|
|
||||||
|
ElapsedTimer {
|
||||||
|
id: timer
|
||||||
|
}
|
||||||
|
|
||||||
|
FrameAnimation {
|
||||||
|
running: root.animated && !root.springSettled
|
||||||
|
onTriggered: {
|
||||||
|
const t = timer.elapsed();
|
||||||
|
|
||||||
|
if (t >= root.springDuration) {
|
||||||
|
root.springSettled = true;
|
||||||
|
} else {
|
||||||
|
const [pos, vel] = root.spring(t);
|
||||||
|
root.morphProgress = Math.min(1, pos); // Overshooting the morph looks weird
|
||||||
|
root.thisLRotation = pos * root.morphAnimRotation;
|
||||||
|
root.scale = 1 + vel * root.morphScale / root.springMaxVelocity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
interval: 650
|
||||||
|
repeat: true
|
||||||
|
triggeredOnStart: true
|
||||||
running: root.animated
|
running: root.animated
|
||||||
loops: Animation.Infinite
|
onTriggered: {
|
||||||
|
root.beginBatchUpdate();
|
||||||
|
root.fromShape = root.toShape;
|
||||||
|
root.shapeIndex = (root.shapeIndex + 1) % root.shapes.length;
|
||||||
|
root.toShape = root.shapes[root.shapeIndex];
|
||||||
|
root.morphProgress = 0;
|
||||||
|
|
||||||
PropertyAction {
|
root.rotation = root.rotation;
|
||||||
target: root
|
root.lRotation = (root.lRotation + root.thisLRotation) % 360;
|
||||||
property: "shapeIndex"
|
root.thisLRotation = 0;
|
||||||
value: (root.shapeIndex + 1) % root.shapes.length
|
root.rotation = Qt.binding(() => root.cRotation + root.lRotation + root.thisLRotation);
|
||||||
}
|
|
||||||
RotationAnimation {
|
|
||||||
target: root
|
|
||||||
property: "lRotation"
|
|
||||||
to: (root.lRotation + root.morphAnimRotation) % 360
|
|
||||||
duration: Tokens.anim.durations.expressiveSlowSpatial
|
|
||||||
easing: Tokens.anim.expressiveSlowSpatial
|
|
||||||
direction: RotationAnimation.Shortest
|
|
||||||
}
|
|
||||||
PauseAnimation {
|
|
||||||
id: morphAnimDelay
|
|
||||||
|
|
||||||
duration: 20
|
root.springSettled = false;
|
||||||
|
timer.restart();
|
||||||
|
root.endBatchUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,7 +108,7 @@ MaterialShape {
|
||||||
to: 360
|
to: 360
|
||||||
easing.type: Easing.Linear
|
easing.type: Easing.Linear
|
||||||
loops: Animation.Infinite
|
loops: Animation.Infinite
|
||||||
duration: 10000
|
duration: 4666
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on color {
|
Behavior on color {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue