|
|
|
@ -4,179 +4,129 @@ |
|
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later |
|
|
|
|
|
|
|
|
|
import QtGraphicalEffects 1.0 |
|
|
|
|
import QtQuick 2.10 |
|
|
|
|
import QtQuick.Controls 2.3 |
|
|
|
|
import QtQuick 2.15 |
|
|
|
|
import QtQuick.Controls 2.15 |
|
|
|
|
|
|
|
|
|
Item { |
|
|
|
|
id: ripple |
|
|
|
|
|
|
|
|
|
property alias clip: backgroundLayer.clip |
|
|
|
|
property real radius: 0 |
|
|
|
|
property color color: "#22000000" |
|
|
|
|
property real maxRadius: Math.max(width, height) |
|
|
|
|
readonly property real radiusAnimationRate: 0.05 |
|
|
|
|
readonly property real radiusTailAnimationRate: 0.5 |
|
|
|
|
readonly 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 |
|
|
|
|
PointHandler { |
|
|
|
|
id: ph |
|
|
|
|
|
|
|
|
|
target: ripple |
|
|
|
|
properties: "radius" |
|
|
|
|
from: 0 |
|
|
|
|
to: ripple.maxRadius |
|
|
|
|
duration: ripple.maxRadius / ripple.radiusAnimationRate |
|
|
|
|
|
|
|
|
|
easing { |
|
|
|
|
type: Easing.OutQuad |
|
|
|
|
} |
|
|
|
|
onGrabChanged: { |
|
|
|
|
circle.centerX = point.position.x |
|
|
|
|
circle.centerY = point.position.y |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
target: Rectangle { |
|
|
|
|
id: backgroundLayer |
|
|
|
|
parent: rippleTarget |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
anchors.fill: parent |
|
|
|
|
color: "transparent" |
|
|
|
|
clip: true |
|
|
|
|
|
|
|
|
|
}, |
|
|
|
|
Transition { |
|
|
|
|
from: "ACTIVE" |
|
|
|
|
to: "NORMAL" |
|
|
|
|
Rectangle { |
|
|
|
|
id: circle |
|
|
|
|
|
|
|
|
|
SequentialAnimation { |
|
|
|
|
ParallelAnimation { |
|
|
|
|
NumberAnimation { |
|
|
|
|
id: radius_tail_animation |
|
|
|
|
property real centerX |
|
|
|
|
property real centerY |
|
|
|
|
|
|
|
|
|
target: ripple |
|
|
|
|
properties: "radius" |
|
|
|
|
to: ripple.maxRadius |
|
|
|
|
duration: ripple.maxRadius / ripple.radiusTailAnimationRate |
|
|
|
|
x: centerX - radius |
|
|
|
|
y: centerY - radius |
|
|
|
|
|
|
|
|
|
easing { |
|
|
|
|
type: Easing.Linear |
|
|
|
|
} |
|
|
|
|
height: radius*2 |
|
|
|
|
width: radius*2 |
|
|
|
|
radius: 0 |
|
|
|
|
color: ripple.color |
|
|
|
|
|
|
|
|
|
state: ph.active ? "ACTIVE" : "NORMAL" |
|
|
|
|
states: [ |
|
|
|
|
State { |
|
|
|
|
name: "NORMAL" |
|
|
|
|
}, |
|
|
|
|
State { |
|
|
|
|
name: "ACTIVE" |
|
|
|
|
} |
|
|
|
|
] |
|
|
|
|
transitions: [ |
|
|
|
|
Transition { |
|
|
|
|
from: "NORMAL" |
|
|
|
|
to: "ACTIVE" |
|
|
|
|
|
|
|
|
|
NumberAnimation { |
|
|
|
|
id: opacity_animation |
|
|
|
|
SequentialAnimation { |
|
|
|
|
//PropertyAction { target: circle; property: "centerX"; value: ph.point.position.x } |
|
|
|
|
//PropertyAction { target: circle; property: "centerY"; value: ph.point.position.y } |
|
|
|
|
PropertyAction { target: circle; property: "visible"; value: true } |
|
|
|
|
PropertyAction { target: circle; property: "opacity"; value: 1 } |
|
|
|
|
|
|
|
|
|
target: ripple |
|
|
|
|
properties: "opacity" |
|
|
|
|
to: 0 |
|
|
|
|
duration: ripple.opacityAnimationDuration |
|
|
|
|
NumberAnimation { |
|
|
|
|
id: radius_animation |
|
|
|
|
|
|
|
|
|
easing { |
|
|
|
|
type: Easing.InQuad |
|
|
|
|
} |
|
|
|
|
target: circle |
|
|
|
|
properties: "radius" |
|
|
|
|
from: 0 |
|
|
|
|
to: ripple.maxRadius |
|
|
|
|
duration: ripple.maxRadius / ripple.radiusAnimationRate |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
easing { |
|
|
|
|
type: Easing.OutQuad |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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(); |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
Transition { |
|
|
|
|
from: "ACTIVE" |
|
|
|
|
to: "NORMAL" |
|
|
|
|
|
|
|
|
|
function onReleased() { |
|
|
|
|
ripple.stop(); |
|
|
|
|
} |
|
|
|
|
SequentialAnimation { |
|
|
|
|
ParallelAnimation { |
|
|
|
|
NumberAnimation { |
|
|
|
|
id: radius_tail_animation |
|
|
|
|
|
|
|
|
|
function onExited() { |
|
|
|
|
ripple.stop(); |
|
|
|
|
} |
|
|
|
|
target: circle |
|
|
|
|
properties: "radius" |
|
|
|
|
to: ripple.maxRadius |
|
|
|
|
duration: ripple.maxRadius / ripple.radiusTailAnimationRate |
|
|
|
|
|
|
|
|
|
function onCanceled() { |
|
|
|
|
ripple.stop(); |
|
|
|
|
} |
|
|
|
|
easing { |
|
|
|
|
type: Easing.Linear |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function onClicked() { |
|
|
|
|
ripple.stop(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
target: rippleTarget |
|
|
|
|
ignoreUnknownSignals: true |
|
|
|
|
} |
|
|
|
|
NumberAnimation { |
|
|
|
|
id: opacity_animation |
|
|
|
|
|
|
|
|
|
Rectangle { |
|
|
|
|
id: backgroundLayer |
|
|
|
|
target: ripple |
|
|
|
|
properties: "opacity" |
|
|
|
|
to: 0 |
|
|
|
|
duration: ripple.opacityAnimationDuration |
|
|
|
|
|
|
|
|
|
anchors.fill: parent |
|
|
|
|
color: "transparent" |
|
|
|
|
clip: true |
|
|
|
|
easing { |
|
|
|
|
type: Easing.InQuad |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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 |
|
|
|
|
} |
|
|
|
|
PropertyAction { target: circle; property: "visible"; value: false } |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
] |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|