fix(ui): smooth label hover animation
This commit is contained in:
@@ -7,13 +7,13 @@ Item {
|
|||||||
required property string artworkSource
|
required property string artworkSource
|
||||||
required property var labelLines
|
required property var labelLines
|
||||||
required property string fontFamily
|
required property string fontFamily
|
||||||
required property int fontPixelSize
|
required property real fontPixelSize
|
||||||
required property string textColor
|
required property string textColor
|
||||||
required property bool textShadowEnabled
|
required property bool textShadowEnabled
|
||||||
required property int verticalSpacing
|
required property int verticalSpacing
|
||||||
required property int horizontalAlignment
|
required property int horizontalAlignment
|
||||||
required property int borderRadius
|
required property int borderRadius
|
||||||
required property int artworkSize
|
required property real artworkSize
|
||||||
property string currentArtworkSource: ""
|
property string currentArtworkSource: ""
|
||||||
property string incomingArtworkSource: ""
|
property string incomingArtworkSource: ""
|
||||||
property real currentArtworkOpacity: 0
|
property real currentArtworkOpacity: 0
|
||||||
|
|||||||
@@ -35,9 +35,17 @@ MouseArea {
|
|||||||
readonly property int hideModeHorizontalPadding: 8
|
readonly property int hideModeHorizontalPadding: 8
|
||||||
readonly property int contentInset: 8
|
readonly property int contentInset: 8
|
||||||
readonly property int labelRailSize: Math.max(0, height - contentInset * 2)
|
readonly property int labelRailSize: Math.max(0, height - contentInset * 2)
|
||||||
readonly property bool mediaControlsShown: mediaControlsEnabled && controlsHoverActive && nowPlayingLabelsVisible && !hideNowPlayingArea
|
readonly property bool mediaControlsTargetShown: mediaControlsEnabled && controlsHoverActive && nowPlayingLabelsVisible && !hideNowPlayingArea
|
||||||
readonly property int labelControlGap: 8
|
readonly property real labelShrunkScale: labelRailSize > 0 ? Math.max(0, (labelRailSize - buttonSize) / labelRailSize) : 1
|
||||||
readonly property int labelContentSize: Math.max(0, labelRailSize - (mediaControlsShown ? buttonSize + labelControlGap : 0))
|
property real labelContentScale: mediaControlsTargetShown ? labelShrunkScale : 1
|
||||||
|
readonly property real controlsReveal: {
|
||||||
|
const range = 1 - labelShrunkScale;
|
||||||
|
if (range <= 0)
|
||||||
|
return mediaControlsTargetShown ? 1 : 0;
|
||||||
|
|
||||||
|
return Math.max(0, Math.min(1, (1 - labelContentScale) / range));
|
||||||
|
}
|
||||||
|
readonly property real labelContentSize: labelRailSize * labelContentScale
|
||||||
readonly property int effectiveImageBorderRadius: Math.max(0, configuredImageBorderRadius)
|
readonly property int effectiveImageBorderRadius: Math.max(0, configuredImageBorderRadius)
|
||||||
readonly property string effectiveBackgroundColor: configuredBackgroundColor || "transparent"
|
readonly property string effectiveBackgroundColor: configuredBackgroundColor || "transparent"
|
||||||
readonly property int effectiveBackgroundRadius: Math.max(0, configuredBackgroundRadius)
|
readonly property int effectiveBackgroundRadius: Math.max(0, configuredBackgroundRadius)
|
||||||
@@ -71,7 +79,7 @@ MouseArea {
|
|||||||
onRawHoverActiveChanged: {
|
onRawHoverActiveChanged: {
|
||||||
if (!mediaControlsMouseArea.mediaControlsEnabled) {
|
if (!mediaControlsMouseArea.mediaControlsEnabled) {
|
||||||
hoverExitTimer.stop();
|
hoverExitTimer.stop();
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
if (rawHoverActive)
|
if (rawHoverActive)
|
||||||
hoverExitTimer.stop();
|
hoverExitTimer.stop();
|
||||||
@@ -81,12 +89,11 @@ MouseArea {
|
|||||||
onMediaControlsEnabledChanged: {
|
onMediaControlsEnabledChanged: {
|
||||||
if (!mediaControlsMouseArea.mediaControlsEnabled)
|
if (!mediaControlsMouseArea.mediaControlsEnabled)
|
||||||
hoverExitTimer.stop();
|
hoverExitTimer.stop();
|
||||||
|
|
||||||
}
|
}
|
||||||
Keys.onPressed: (event) => {
|
Keys.onPressed: event => {
|
||||||
if (!mediaControlsMouseArea.mediaControlsEnabled) {
|
if (!mediaControlsMouseArea.mediaControlsEnabled) {
|
||||||
event.accepted = false;
|
event.accepted = false;
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
if (!event.modifiers) {
|
if (!event.modifiers) {
|
||||||
event.accepted = true;
|
event.accepted = true;
|
||||||
@@ -114,6 +121,13 @@ MouseArea {
|
|||||||
interval: 300
|
interval: 300
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Behavior on labelContentScale {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: 250
|
||||||
|
easing.type: Easing.InOutQuad
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
visible: mediaControlsMouseArea.usesCustomBackground
|
visible: mediaControlsMouseArea.usesCustomBackground
|
||||||
@@ -126,7 +140,7 @@ MouseArea {
|
|||||||
anchors.margins: mediaControlsMouseArea.contentInset
|
anchors.margins: mediaControlsMouseArea.contentInset
|
||||||
layoutDirection: mediaControlsMouseArea.labelsOnRight ? Qt.RightToLeft : Qt.LeftToRight
|
layoutDirection: mediaControlsMouseArea.labelsOnRight ? Qt.RightToLeft : Qt.LeftToRight
|
||||||
|
|
||||||
ColumnLayout {
|
Item {
|
||||||
id: leftColumn
|
id: leftColumn
|
||||||
|
|
||||||
visible: !mediaControlsMouseArea.hideNowPlayingArea
|
visible: !mediaControlsMouseArea.hideNowPlayingArea
|
||||||
@@ -134,43 +148,54 @@ MouseArea {
|
|||||||
Layout.minimumWidth: visible ? mediaControlsMouseArea.labelRailSize : 0
|
Layout.minimumWidth: visible ? mediaControlsMouseArea.labelRailSize : 0
|
||||||
Layout.preferredWidth: visible ? mediaControlsMouseArea.labelRailSize : 0
|
Layout.preferredWidth: visible ? mediaControlsMouseArea.labelRailSize : 0
|
||||||
Layout.maximumWidth: visible ? mediaControlsMouseArea.labelRailSize : 0
|
Layout.maximumWidth: visible ? mediaControlsMouseArea.labelRailSize : 0
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
ColumnLayout {
|
Item {
|
||||||
id: nowPlayingLabels
|
id: labelSlot
|
||||||
|
|
||||||
Layout.alignment: mediaControlsMouseArea.labelsOnRight ? Qt.AlignLeft : Qt.AlignRight
|
readonly property bool showsArtwork: mediaControlsMouseArea.configuredUseLabelArtwork && player.artUrl.length > 0
|
||||||
Layout.fillWidth: true
|
// Text is rasterized at whole pixel sizes, then lightly scaled between steps for smoother motion.
|
||||||
|
readonly property real textTargetFontSize: Math.max(1, mediaControlsMouseArea.effectiveLabelFontSize * mediaControlsMouseArea.labelContentScale)
|
||||||
|
readonly property int textRasterFontSize: Math.max(1, Math.round(textTargetFontSize))
|
||||||
|
readonly property real textResidualScale: textTargetFontSize / textRasterFontSize
|
||||||
|
|
||||||
|
x: mediaControlsMouseArea.labelsOnRight ? 0 : leftColumn.width - width
|
||||||
|
y: 0
|
||||||
|
width: mediaControlsMouseArea.labelContentSize
|
||||||
|
height: mediaControlsMouseArea.labelContentSize
|
||||||
|
clip: true
|
||||||
visible: mediaControlsMouseArea.nowPlayingLabelsVisible
|
visible: mediaControlsMouseArea.nowPlayingLabelsVisible
|
||||||
|
|
||||||
LabelContent {
|
LabelContent {
|
||||||
Layout.alignment: mediaControlsMouseArea.labelsOnRight ? Qt.AlignLeft : Qt.AlignRight
|
anchors.left: parent.left
|
||||||
Layout.preferredWidth: mediaControlsMouseArea.labelContentSize
|
anchors.top: parent.top
|
||||||
Layout.preferredHeight: mediaControlsMouseArea.labelContentSize
|
width: labelSlot.showsArtwork ? mediaControlsMouseArea.labelRailSize : mediaControlsMouseArea.labelContentSize / labelSlot.textResidualScale
|
||||||
Layout.maximumWidth: mediaControlsMouseArea.labelRailSize
|
height: labelSlot.showsArtwork ? mediaControlsMouseArea.labelRailSize : mediaControlsMouseArea.labelContentSize / labelSlot.textResidualScale
|
||||||
Layout.maximumHeight: mediaControlsMouseArea.labelRailSize
|
scale: labelSlot.showsArtwork ? mediaControlsMouseArea.labelContentScale : labelSlot.textResidualScale
|
||||||
|
transformOrigin: Item.TopLeft
|
||||||
artworkSource: mediaControlsMouseArea.configuredUseLabelArtwork ? player.artUrl : ""
|
artworkSource: mediaControlsMouseArea.configuredUseLabelArtwork ? player.artUrl : ""
|
||||||
labelLines: mediaControlsMouseArea.effectiveLabelLines
|
labelLines: mediaControlsMouseArea.effectiveLabelLines
|
||||||
fontFamily: mediaControlsMouseArea.configuredFontFamily
|
fontFamily: mediaControlsMouseArea.configuredFontFamily
|
||||||
fontPixelSize: mediaControlsMouseArea.effectiveLabelFontSize
|
fontPixelSize: labelSlot.showsArtwork ? mediaControlsMouseArea.effectiveLabelFontSize : labelSlot.textRasterFontSize
|
||||||
textColor: mediaControlsMouseArea.effectiveForegroundColor
|
textColor: mediaControlsMouseArea.effectiveForegroundColor
|
||||||
textShadowEnabled: mediaControlsMouseArea.configuredTextShadowEnabled
|
textShadowEnabled: mediaControlsMouseArea.configuredTextShadowEnabled
|
||||||
verticalSpacing: mediaControlsMouseArea.effectiveLabelVerticalSpacing
|
verticalSpacing: mediaControlsMouseArea.effectiveLabelVerticalSpacing
|
||||||
horizontalAlignment: mediaControlsMouseArea.labelsOnRight ? Text.AlignLeft : Text.AlignRight
|
horizontalAlignment: mediaControlsMouseArea.labelsOnRight ? Text.AlignLeft : Text.AlignRight
|
||||||
borderRadius: mediaControlsMouseArea.effectiveImageBorderRadius
|
borderRadius: mediaControlsMouseArea.effectiveImageBorderRadius
|
||||||
artworkSize: mediaControlsMouseArea.labelContentSize
|
artworkSize: labelSlot.showsArtwork ? mediaControlsMouseArea.labelRailSize : mediaControlsMouseArea.labelContentSize / labelSlot.textResidualScale
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: mediaControls
|
id: mediaControls
|
||||||
|
|
||||||
Layout.alignment: mediaControlsMouseArea.labelsOnRight ? Qt.AlignLeft : Qt.AlignRight
|
x: mediaControlsMouseArea.labelsOnRight ? 0 : leftColumn.width - width
|
||||||
Layout.topMargin: visible ? mediaControlsMouseArea.labelControlGap : 0
|
y: mediaControlsMouseArea.labelContentSize
|
||||||
enabled: mediaControlsMouseArea.mediaControlsShown
|
width: implicitWidth
|
||||||
opacity: mediaControlsMouseArea.mediaControlsShown ? 1 : 0
|
height: mediaControlsMouseArea.buttonSize
|
||||||
visible: mediaControlsMouseArea.mediaControlsShown
|
clip: true
|
||||||
|
enabled: mediaControlsMouseArea.mediaControlsTargetShown
|
||||||
|
opacity: mediaControlsMouseArea.controlsReveal
|
||||||
|
visible: mediaControlsMouseArea.mediaControlsTargetShown || opacity > 0
|
||||||
|
|
||||||
QQC2.Button {
|
QQC2.Button {
|
||||||
Layout.preferredWidth: buttonSize
|
Layout.preferredWidth: buttonSize
|
||||||
@@ -186,7 +211,6 @@ MouseArea {
|
|||||||
source: "media-skip-backward"
|
source: "media-skip-backward"
|
||||||
color: mediaControlsMouseArea.effectiveForegroundColor
|
color: mediaControlsMouseArea.effectiveForegroundColor
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QQC2.Button {
|
QQC2.Button {
|
||||||
@@ -205,7 +229,6 @@ MouseArea {
|
|||||||
source: player.playbackStatus === 2 ? "media-playback-pause" : "media-playback-start"
|
source: player.playbackStatus === 2 ? "media-playback-pause" : "media-playback-start"
|
||||||
color: mediaControlsMouseArea.effectiveForegroundColor
|
color: mediaControlsMouseArea.effectiveForegroundColor
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QQC2.Button {
|
QQC2.Button {
|
||||||
@@ -219,19 +242,8 @@ MouseArea {
|
|||||||
source: "media-skip-forward"
|
source: "media-skip-forward"
|
||||||
color: mediaControlsMouseArea.effectiveForegroundColor
|
color: mediaControlsMouseArea.effectiveForegroundColor
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
PropertyAnimation {
|
|
||||||
duration: 250
|
|
||||||
easing.type: Easing.InOutQuad
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
@@ -252,7 +264,6 @@ MouseArea {
|
|||||||
height: Math.round(parent.height * mediaControlsMouseArea.effectiveSeparatorHeight / 100)
|
height: Math.round(parent.height * mediaControlsMouseArea.effectiveSeparatorHeight / 100)
|
||||||
color: mediaControlsMouseArea.configuredHideSeparator ? "transparent" : mediaControlsMouseArea.effectiveForegroundColor
|
color: mediaControlsMouseArea.configuredHideSeparator ? "transparent" : mediaControlsMouseArea.effectiveForegroundColor
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
@@ -289,9 +300,6 @@ MouseArea {
|
|||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
horizontalAlignment: mediaControlsMouseArea.labelsOnRight ? Text.AlignRight : Text.AlignLeft
|
horizontalAlignment: mediaControlsMouseArea.labelsOnRight ? Text.AlignRight : Text.AlignLeft
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user