Kirigami2

Hero.qml
1 /*
2  * SPDX-FileCopyrightText: 2020 Marco Martin <[email protected]>
3  * SPDX-FileCopyrightText: 2020 Carson Black <[email protected]>
4  *
5  * SPDX-License-Identifier: LGPL-2.0-or-later
6  */
7 
8 import QtQuick 2.14
9 import QtQuick.Controls 2.4 as QQC2
10 import org.kde.kirigami 2.13 as Kirigami
11 
12 /**
13  * @brief An element that implements a shared element transition, otherwise known as a "hero animation".
14  */
15 Item {
16  id: root
17 
18 //BEGIN properties
19  /**
20  * @brief This property holds the item to animate from in the Hero animation.
21  */
22  property Item source
23 
24  /**
25  * @brief This property holds the item to animate to in the Hero animation.
26  */
27  property Item destination
28 
29  /**
30  * @brief This property sets whether the source item will reappear
31  * in the original position when the Hero animation completes.
32  *
33  * default: ``true``
34  */
35  property bool restore: true
36 
37  /**
38  * Group of properties related to the mask of the object when performing a hero animation.
39  * This contains the default mask as well as the properties required to create a custom mask.
40  *
41  * The default mask of the Hero will transition from a circle to a rectangle on open(), and
42  * from a rectangle to a circle on close().
43  *
44  * * ``sourceProgress: real`` the progress of the animation, where 0 is the start and 1 is the end.
45  * * ``destinationProgress: real`` the progress of the animation, where 1 is the start and 0 is the end.
46  * * ``mask.sourceHeight: real`` the height of the source item.
47  * * ``mask.sourceWidth: real`` the width of the source item.
48  * * ``mask.destinationWidth: real`` the width of the destination item.
49  * * ``mask.destinationHeight: real`` the height of the destination item.
50  * * ``item: Rectangle`` the item used to mask the Hero during animation. This should bind to the sourceProgress and destinationProgress to change as the animation progresses.
51  *
52  */
53  readonly property QtObject mask: QtObject {
54  /**
55  * @brief This property holds the progress of the animation,
56  * where 0 is the start and 1 is the end.
57  */
58  readonly property real sourceProgress: sourceEffect.progress
59 
60  /**
61  * @brief This property holds the progress of the animation,
62  * where 1 is the start and 0 is the end.
63  */
64  readonly property real destinationProgress: destinationEffect.progress
65 
66  /**
67  * @brief This property holds the height of the source item.
68  */
69  readonly property real sourceHeight: sourceEffect.height
70 
71  /**
72  * @brief This property holds the width of the source item.
73  */
74  readonly property real sourceWidth: sourceEffect.width
75 
76  /**
77  * @brief This property holds the width of the destination item.
78  */
79  readonly property real destinationWidth: destinationEffect.width
80 
81  /**
82  * @brief This property holds the height of the destination item.
83  */
84  readonly property real destinationHeight: destinationEffect.height
85 
86  /**
87  * @brief This property holds the item used to mask the Hero during animation.
88  *
89  * This should bind to the sourceProgress and destinationProgress to change as the animation progresses.
90  */
91  property Item item: Rectangle {
92  visible: false
93  color: "white"
94 
95  radius: (width/2) * mask.destinationProgress
96  width: (mask.sourceWidth * mask.sourceProgress) + (mask.destinationWidth * mask.destinationProgress)
97  height: (mask.sourceHeight * mask.sourceProgress) + (mask.destinationHeight * mask.destinationProgress)
98 
99  layer.enabled: true
100  layer.smooth: true
101  }
102  }
103 
104  property alias duration: sourceAni.duration
105  readonly property QtObject easing: QtObject {
106  property alias amplitude: sourceAni.easing.amplitude
107  property alias bezierCurve: sourceAni.easing.bezierCurve
108  property alias overshoot: sourceAni.easing.overshoot
109  property alias period: sourceAni.easing.period
110  property alias type: sourceAni.easing.type
111  }
112 //END properties
113 
114  function open() {
115  if (source !== null && destination !== null && !heroAnimation.running) {
116  heroAnimation.source = source
117  heroAnimation.destination = destination
118  heroAnimation.restart()
119  }
120  }
121  function close() {
122  if (source !== null && destination !== null && !heroAnimation.running) {
123  // doing a switcheroo simplifies the code
124  heroAnimation.source = destination
125  heroAnimation.destination = source
126  heroAnimation.restart()
127  }
128  }
129 
130  SequentialAnimation {
131  id: heroAnimation
132 
133  property Item source: Item {}
134  property Item destination: Item {}
135 
136  ScriptAction {
137  script: {
138  heroAnimation.source.layer.enabled = true
139  heroAnimation.source.layer.smooth = true
140  heroAnimation.destination.layer.enabled = true
141  heroAnimation.destination.layer.smooth = true
142  sourceEffect.visible = true
143  destinationEffect.visible = true
144  sourceEffect.source = null
145  sourceEffect.source = heroAnimation.source
146  destinationEffect.source = null
147  destinationEffect.source = heroAnimation.destination
148  heroAnimation.source.opacity = 0
149  heroAnimation.destination.opacity = 0
150  sourceEffect.parent.visible = true
151  }
152  }
153  ParallelAnimation {
154  NumberAnimation {
155  id: sourceAni
156 
157  target: sourceEffect
158  property: "progress"
159  from: 0
160  to: 1
161  duration: Kirigami.Units.longDuration
162  easing.type: Easing.InOutQuad
163  }
164  NumberAnimation {
165  target: destinationEffect
166  property: "progress"
167  from: 1
168  to: 0
169  duration: root.duration
170  easing.amplitude: root.easing.amplitude
171  easing.bezierCurve: root.easing.bezierCurve
172  easing.overshoot: root.easing.overshoot
173  easing.period: root.easing.period
174  easing.type: root.easing.type
175  }
176  }
177  ScriptAction {
178  script: {
179  sourceEffect.visible = false
180  destinationEffect.visible = false
181  heroAnimation.source.layer.enabled = false
182  heroAnimation.source.layer.smooth = false
183  heroAnimation.destination.layer.enabled = false
184  heroAnimation.destination.layer.smooth = false
185  heroAnimation.destination.opacity = 1
186  if (root.restore) {
187  heroAnimation.source.opacity = 1
188  }
189  sourceEffect.parent.visible = false
190  }
191  }
192 
193  }
194 
195  QtObject {
196  id: __privateShaderSources
197  readonly property string vertexShader: `
198 uniform highp mat4 qt_Matrix;
199 attribute highp vec4 qt_Vertex;
200 attribute highp vec2 qt_MultiTexCoord0;
201 varying highp vec2 qt_TexCoord0;
202 uniform highp float startX;
203 uniform highp float startY;
204 uniform highp float targetX;
205 uniform highp float targetY;
206 uniform highp float scaleWidth;
207 uniform highp float scaleHeight;
208 uniform highp float progress;
209 
210 highp mat4 morph = mat4(1.0 + (scaleWidth - 1.0) * progress, 0.0, 0.0, startX*(1.0-progress) + targetX*progress,
211  0.0, 1.0 + (scaleHeight - 1.0) * progress, 0.0, startY*(1.0-progress) + targetY*progress,
212  0.0, 0.0, 1.0, 0.0,
213  0.0, 0.0, 0.0, 1.0);
214 
215 void main() {
216  qt_TexCoord0 = qt_MultiTexCoord0;
217  gl_Position = qt_Matrix * qt_Vertex * morph;
218 }
219  `
220  }
221 
222  ShaderEffect {
223  id: sourceEffect
224  x: 0
225  y: 0
226  parent: heroAnimation.source.QQC2.Overlay.overlay
227  width: heroAnimation.source.width
228  height: heroAnimation.source.height
229  visible: false
230  property variant source: heroAnimation.source
231  property real progress: 0
232  property real startX: heroAnimation.source.Kirigami.ScenePosition.x / (applicationWindow().width / 2)
233  property real startY: -heroAnimation.source.Kirigami.ScenePosition.y / (applicationWindow().height / 2)
234 
235  property real targetX: scaleWidth - 1 + (heroAnimation.destination.Kirigami.ScenePosition.x * 2) / applicationWindow().width
236  property real targetY: 1-scaleHeight - (heroAnimation.destination.Kirigami.ScenePosition.y * 2) / applicationWindow().height
237  property real scaleWidth: heroAnimation.destination.width/heroAnimation.source.width
238  property real scaleHeight: heroAnimation.destination.height/heroAnimation.source.height
239  vertexShader: __privateShaderSources.vertexShader
240  fragmentShader: `
241 varying highp vec2 qt_TexCoord0;
242 uniform sampler2D source;
243 uniform lowp float qt_Opacity;
244 uniform lowp float progress;
245 void main() {
246  gl_FragColor = texture2D(source, qt_TexCoord0) * qt_Opacity * (1.0 - progress);
247 }
248  `
249  }
250 
251  ShaderEffect {
252  id: destinationEffect
253  x: 0
254  y: 0
255  parent: heroAnimation.destination.QQC2.Overlay.overlay
256  width: heroAnimation.destination.width
257  height: heroAnimation.destination.height
258  visible: false
259  property variant source: heroAnimation.destination
260  property real progress: sourceEffect.progress
261  property real startX: heroAnimation.destination.Kirigami.ScenePosition.x / (applicationWindow().width / 2)
262  property real startY: -heroAnimation.destination.Kirigami.ScenePosition.y / (applicationWindow().height / 2)
263 
264  property real targetX: scaleWidth - 1 + (heroAnimation.source.Kirigami.ScenePosition.x * 2) / applicationWindow().width
265  property real targetY: 1-scaleHeight - (heroAnimation.source.Kirigami.ScenePosition.y * 2) / applicationWindow().height
266  property real scaleWidth: heroAnimation.source.width/heroAnimation.destination.width
267  property real scaleHeight: heroAnimation.source.height/heroAnimation.destination.height
268 
269  property variant maskSource: root.mask.item
270 
271  vertexShader: __privateShaderSources.vertexShader
272  fragmentShader: `
273 varying highp vec2 qt_TexCoord0;
274 uniform sampler2D source;
275 uniform sampler2D maskSource;
276 uniform lowp float qt_Opacity;
277 uniform lowp float progress;
278 void main() {
279  gl_FragColor = texture2D(source, qt_TexCoord0) * texture2D(maskSource, qt_TexCoord0).a * qt_Opacity * (1.0 - progress);
280 }
281  `
282  }
283 }
const QList< QKeySequence > & close()
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Feb 7 2023 04:14:23 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.