Add Ripple effects to qml buttons and avatar

This commit is contained in:
Joseph Donofry 2021-01-11 17:50:26 -05:00
parent 102ef05cfe
commit 1bc2db4bdf
No known key found for this signature in database
GPG key ID: E8A1D78EF044B0CB
5 changed files with 194 additions and 0 deletions

View file

@ -1,3 +1,4 @@
import "./ui"
import QtGraphicalEffects 1.0 import QtGraphicalEffects 1.0
import QtQuick 2.6 import QtQuick 2.6
import QtQuick.Controls 2.3 import QtQuick.Controls 2.3
@ -43,6 +44,12 @@ Rectangle {
anchors.fill: parent anchors.fill: parent
onClicked: TimelineManager.openImageOverlay(TimelineManager.timeline.avatarUrl(userid), TimelineManager.timeline.data.id) onClicked: TimelineManager.openImageOverlay(TimelineManager.timeline.avatarUrl(userid), TimelineManager.timeline.data.id)
Ripple {
rippleTarget: mouseArea
color: Qt.rgba(colors.alternateBase.r, colors.alternateBase.g, colors.alternateBase.b, 0.5)
}
} }
layer.effect: OpacityMask { layer.effect: OpacityMask {

View file

@ -1,3 +1,4 @@
import "./ui"
import QtQuick 2.3 import QtQuick 2.3
import QtQuick.Controls 2.3 import QtQuick.Controls 2.3
@ -28,4 +29,10 @@ AbstractButton {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
} }
Ripple {
color: Qt.rgba(buttonTextColor.r, buttonTextColor.g, buttonTextColor.b, 0.5)
clip: false
rippleTarget: button
}
} }

177
resources/qml/ui/Ripple.qml Normal file
View file

@ -0,0 +1,177 @@
import QtGraphicalEffects 1.10
import QtQuick 2.10
import QtQuick.Controls 2.3
Item {
id: ripple
property alias clip: backgroundLayer.clip
property real radius: 0
property color color: "#22000000"
property real maxRadius: Math.max(width, height)
property real radiusAnimationRate: 0.05
property real radiusTailAnimationRate: 0.5
property real opacityAnimationDuration: 300
readonly property real diameter: radius * 2
property real centerX
property real centerY
property var rippleTarget: parent
function start() {
console.log("Starting ripple animation");
ripple.state = "ACTIVE";
}
function stop() {
console.log("Stopping ripple animation");
ripple.state = "NORMAL";
}
anchors.fill: parent
state: "NORMAL"
states: [
State {
name: "NORMAL"
},
State {
name: "ACTIVE"
}
]
transitions: [
Transition {
from: "NORMAL"
to: "ACTIVE"
SequentialAnimation {
ScriptAction {
script: {
ripple.opacity = 1;
ripple.visible = true;
}
}
NumberAnimation {
id: radius_animation
target: ripple
properties: "radius"
from: 0
to: ripple.maxRadius
duration: ripple.maxRadius / ripple.radiusAnimationRate
easing {
type: Easing.OutQuad
}
}
}
},
Transition {
from: "ACTIVE"
to: "NORMAL"
SequentialAnimation {
ParallelAnimation {
NumberAnimation {
id: radius_tail_animation
target: ripple
properties: "radius"
to: ripple.maxRadius
duration: ripple.maxRadius / ripple.radiusTailAnimationRate
easing {
type: Easing.Linear
}
}
NumberAnimation {
id: opacity_animation
target: ripple
properties: "opacity"
to: 0
duration: ripple.opacityAnimationDuration
easing {
type: Easing.InQuad
}
}
}
ScriptAction {
script: {
ripple.visible = false;
}
}
}
}
]
Connections {
function onPressed(mouse) {
// Button
// Default to center
// MouseArea
if (mouse) {
ripple.centerX = mouse.x;
ripple.centerY = mouse.y;
} else if (rippleTarget.pressX) {
ripple.centerX = rippleTarget.pressX;
ripple.centerY = rippleTarget.pressY;
} else {
ripple.centerX = width / 2;
ripple.centerY = height / 2;
}
ripple.start();
}
function onReleased() {
ripple.stop();
}
function onExited() {
ripple.stop();
}
function onCanceled() {
ripple.stop();
}
function onClicked() {
ripple.stop();
}
target: rippleTarget
ignoreUnknownSignals: true
}
Rectangle {
id: backgroundLayer
anchors.fill: parent
color: "transparent"
clip: true
Rectangle {
id: circle
x: ripple.centerX - ripple.radius
y: ripple.centerY - ripple.radius
height: ripple.diameter
width: ripple.diameter
radius: ripple.radius
color: ripple.color
}
}
}

2
resources/qml/ui/qmldir Normal file
View file

@ -0,0 +1,2 @@
module im.nheko.UI
Ripple 1.0 Ripple.qml

View file

@ -159,6 +159,7 @@
<file>qml/device-verification/NewVerificationRequest.qml</file> <file>qml/device-verification/NewVerificationRequest.qml</file>
<file>qml/device-verification/Failed.qml</file> <file>qml/device-verification/Failed.qml</file>
<file>qml/device-verification/Success.qml</file> <file>qml/device-verification/Success.qml</file>
<file>qml/ui/Ripple.qml</file>
</qresource> </qresource>
<qresource prefix="/media"> <qresource prefix="/media">
<file>media/ring.ogg</file> <file>media/ring.ogg</file>