1 files changed, 177 insertions, 0 deletions
diff --git a/resources/qml/ui/Ripple.qml b/resources/qml/ui/Ripple.qml
new file mode 100644
index 00000000..93380f77
--- /dev/null
+++ b/resources/qml/ui/Ripple.qml
@@ -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 {
+ // Button
+ // Default to center
+
+ function onPressed(mouse) {
+ // 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
+ }
+
+ }
+
+}
|