feat: improve slider

This commit is contained in:
2 * r + 2 * t 2026-05-04 00:14:33 +10:00
parent 000c9a459b
commit 5e59b5e2a4

View file

@ -1,5 +1,7 @@
import QtQuick
import QtQuick.Templates
import Caelestia
import Caelestia.Components
import Caelestia.Config
import qs.components
import qs.services
@ -7,51 +9,152 @@ import qs.services
Slider {
id: root
background: Item {
property bool wavy: true
property bool animateWave
property alias waveFrequency: wave.frequency
property alias waveDuration: waveAnim.duration
property color fgColour: enabled ? Colours.palette.m3primary : Qt.alpha(Colours.palette.m3onSurface, 0.38)
property color bgColour: enabled ? Colours.palette.m3secondaryContainer : Qt.alpha(Colours.palette.m3onSurface, 0.1)
property real pos: visualPosition
signal interaction(v: real)
implicitWidth: 200
implicitHeight: 8
contentItem: Item {
anchors.fill: parent
StyledRect {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.topMargin: root.implicitHeight / 3
anchors.bottomMargin: root.implicitHeight / 3
id: remaining
implicitWidth: root.handle.x - root.implicitHeight / 6
anchors.left: handle.right
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Tokens.spacing.extraSmall
implicitHeight: Math.min(width, parent.height)
opacity: implicitHeight / parent.height
color: Colours.palette.m3primary
radius: Tokens.rounding.full
topRightRadius: root.implicitHeight / 15
bottomRightRadius: root.implicitHeight / 15
topLeftRadius: Tokens.rounding.extraSmall / 2
bottomLeftRadius: Tokens.rounding.extraSmall / 2
color: root.bgColour
}
StyledRect {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.topMargin: root.implicitHeight / 3
anchors.bottomMargin: root.implicitHeight / 3
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: (parent.height - implicitHeight) / 2 * remaining.opacity
implicitWidth: parent.width - root.handle.x - root.handle.implicitWidth - root.implicitHeight / 6
implicitWidth: implicitHeight
implicitHeight: 4 * remaining.opacity
opacity: remaining.opacity
color: Colours.palette.m3surfaceContainerHighest
radius: Tokens.rounding.full
topLeftRadius: root.implicitHeight / 15
bottomLeftRadius: root.implicitHeight / 15
color: root.fgColour
}
StyledRect {
id: handle
anchors.left: wave.right
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Tokens.spacing.extraSmall
implicitWidth: parent.height * 0.75
implicitHeight: parent.height * (mouse.pressed ? 5 : 4)
radius: Tokens.rounding.full
color: root.fgColour
Behavior on implicitHeight {
Anim {
type: Anim.FastSpatial
}
}
}
WavyLine {
id: wave
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
implicitHeight: lineWidth * amplitudeMultiplier * 2 + lineWidth
lineWidth: parent.height - 1
amplitudeMultiplier: root.wavy ? 0.5 : 0
startX: x
fullLength: parent.width - handle.implicitWidth - handle.anchors.leftMargin
color: root.fgColour
Component.onCompleted: implicitWidth = Qt.binding(() => fullLength * root.pos)
Anim on waveProgress {
id: waveAnim
running: true
paused: !root.animateWave
from: 0
to: 1
duration: 1000
easing.type: Easing.Linear
loops: Animation.Infinite
}
Behavior on amplitudeMultiplier {
Anim {
type: Anim.DefaultEffects
}
}
Behavior on color {
CAnim {}
}
Behavior on implicitWidth {
id: widthBehavior
Anim {}
}
}
}
handle: StyledRect {
x: root.visualPosition * root.availableWidth - implicitWidth / 2
Binding {
id: posBinding
implicitWidth: root.implicitHeight / 4.5
implicitHeight: root.implicitHeight
target: root
property: "pos"
value: CUtils.clamp(mouse.pressStartPos + mouse.dragMovement, 0, 1)
when: mouse.pressed
}
color: Colours.palette.m3primary
radius: Tokens.rounding.full
MouseArea {
id: mouse
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
cursorShape: Qt.PointingHandCursor
property real pressStartX
property real pressStartPos
property real dragMovement
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
preventStealing: true
implicitHeight: handle.implicitHeight
onPressed: e => {
widthBehavior.enabled = false;
pressStartX = e.x;
pressStartPos = root.visualPosition;
}
onPositionChanged: e => dragMovement = (e.x - pressStartX) / width
onReleased: e => {
root.interaction(posBinding.value);
widthBehavior.enabled = true;
dragMovement = 0;
}
}
}