Warning, /frameworks/kirigami/src/controls/Hero.qml is written in an unsupported language. File is not indexed.

0001 /*
0002  *  SPDX-FileCopyrightText: 2020 Marco Martin <mart@kde.org>
0003  *  SPDX-FileCopyrightText: 2020 Carson Black <uhhadd@gmail.com>
0004  *
0005  *  SPDX-License-Identifier: LGPL-2.0-or-later
0006  */
0007 
0008 import QtQuick 2.14
0009 import QtQuick.Controls 2.4 as QQC2
0010 import org.kde.kirigami 2.13 as Kirigami
0011 
0012 /**
0013  * @brief An element that implements a shared element transition, otherwise known as a "hero animation".
0014  */
0015 Item {
0016     id: root
0017 
0018 //BEGIN properties
0019     /**
0020      * @brief This property holds the item to animate from in the Hero animation.
0021      */
0022     property Item source
0023 
0024     /**
0025      * @brief This property holds the item to animate to in the Hero animation.
0026      */
0027     property Item destination
0028 
0029     /**
0030      * @brief This property sets whether the source item will reappear
0031      * in the original position when the Hero animation completes.
0032      *
0033      * default: ``true``
0034      */
0035     property bool restore: true
0036 
0037     /**
0038      * Group of properties related to the mask of the object when performing a hero animation.
0039      * This contains the default mask as well as the properties required to create a custom mask.
0040      *
0041      * The default mask of the Hero will transition from a circle to a rectangle on open(), and
0042      * from a rectangle to a circle on close().
0043      *
0044      * This grouped property has the following sub-properties:
0045      * * ``sourceProgress: real`` the progress of the animation, where 0 is the start and 1 is the end.
0046      * * ``destinationProgress: real`` the progress of the animation, where 1 is the start and 0 is the end.
0047      * * ``mask.sourceHeight: real`` the height of the source item.
0048      * * ``mask.sourceWidth: real`` the width of the source item.
0049      * * ``mask.destinationWidth: real`` the width of the destination item.
0050      * * ``mask.destinationHeight: real`` the height of the destination item.
0051      * * ``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.
0052      *
0053      */
0054     readonly property QtObject mask: QtObject {
0055         /**
0056          * @brief This property holds the progress of the animation,
0057          * where 0 is the start and 1 is the end.
0058          */
0059         readonly property real sourceProgress: sourceEffect.progress
0060 
0061         /**
0062          * @brief This property holds the progress of the animation,
0063          * where 1 is the start and 0 is the end.
0064          */
0065         readonly property real destinationProgress: destinationEffect.progress
0066 
0067         /**
0068          * @brief This property holds the height of the source item.
0069          */
0070         readonly property real sourceHeight: sourceEffect.height
0071 
0072         /**
0073         * @brief This property holds the width of the source item.
0074         */
0075         readonly property real sourceWidth: sourceEffect.width
0076 
0077         /**
0078          * @brief This property holds the width of the destination item.
0079          */
0080         readonly property real destinationWidth: destinationEffect.width
0081 
0082         /**
0083          * @brief This property holds the height of the destination item.
0084          */
0085         readonly property real destinationHeight: destinationEffect.height
0086 
0087         /**
0088          * @brief This property holds the item used to mask the Hero during animation.
0089          *
0090          * This should bind to the sourceProgress and destinationProgress to change as the animation progresses.
0091          */
0092         property Item item: Rectangle {
0093             visible: false
0094             color: "white"
0095 
0096             radius: (width/2) * mask.destinationProgress
0097             width: (mask.sourceWidth * mask.sourceProgress) + (mask.destinationWidth * mask.destinationProgress)
0098             height: (mask.sourceHeight * mask.sourceProgress) + (mask.destinationHeight * mask.destinationProgress)
0099 
0100             layer.enabled: true
0101             layer.smooth: true
0102         }
0103     }
0104 
0105     property alias duration: sourceAni.duration
0106     readonly property QtObject easing: QtObject {
0107         property alias amplitude: sourceAni.easing.amplitude
0108         property alias bezierCurve: sourceAni.easing.bezierCurve
0109         property alias overshoot: sourceAni.easing.overshoot
0110         property alias period: sourceAni.easing.period
0111         property alias type: sourceAni.easing.type
0112     }
0113 //END properties
0114 
0115     function open() {
0116         if (source !== null && destination !== null && !heroAnimation.running) {
0117             heroAnimation.source = source
0118             heroAnimation.destination = destination
0119             heroAnimation.restart()
0120         }
0121     }
0122     function close() {
0123         if (source !== null && destination !== null && !heroAnimation.running) {
0124             // doing a switcheroo simplifies the code
0125             heroAnimation.source = destination
0126             heroAnimation.destination = source
0127             heroAnimation.restart()
0128         }
0129     }
0130 
0131     SequentialAnimation {
0132         id: heroAnimation
0133 
0134         property Item source: Item {}
0135         property Item destination: Item {}
0136 
0137         ScriptAction {
0138             script: {
0139                 heroAnimation.source.layer.enabled = true
0140                 heroAnimation.source.layer.smooth = true
0141                 heroAnimation.destination.layer.enabled = true
0142                 heroAnimation.destination.layer.smooth = true
0143                 sourceEffect.visible = true
0144                 destinationEffect.visible = true
0145                 sourceEffect.source = null
0146                 sourceEffect.source = heroAnimation.source
0147                 destinationEffect.source = null
0148                 destinationEffect.source = heroAnimation.destination
0149                 heroAnimation.source.opacity = 0
0150                 heroAnimation.destination.opacity = 0
0151                 sourceEffect.parent.visible = true
0152             }
0153         }
0154         ParallelAnimation {
0155             NumberAnimation {
0156                 id: sourceAni
0157 
0158                 target: sourceEffect
0159                 property: "progress"
0160                 from: 0
0161                 to: 1
0162                 duration: Kirigami.Units.longDuration
0163                 easing.type: Easing.InOutQuad
0164             }
0165             NumberAnimation {
0166                 target: destinationEffect
0167                 property: "progress"
0168                 from: 1
0169                 to: 0
0170                 duration: root.duration
0171                 easing.amplitude: root.easing.amplitude
0172                 easing.bezierCurve: root.easing.bezierCurve
0173                 easing.overshoot: root.easing.overshoot
0174                 easing.period: root.easing.period
0175                 easing.type: root.easing.type
0176             }
0177         }
0178         ScriptAction {
0179             script: {
0180                 sourceEffect.visible = false
0181                 destinationEffect.visible = false
0182                 heroAnimation.source.layer.enabled = false
0183                 heroAnimation.source.layer.smooth = false
0184                 heroAnimation.destination.layer.enabled = false
0185                 heroAnimation.destination.layer.smooth = false
0186                 heroAnimation.destination.opacity = 1
0187                 if (root.restore) {
0188                     heroAnimation.source.opacity = 1
0189                 }
0190                 sourceEffect.parent.visible = false
0191             }
0192         }
0193 
0194     }
0195 
0196     QtObject {
0197         id: __privateShaderSources
0198         readonly property string vertexShader: `
0199 uniform highp mat4 qt_Matrix;
0200 attribute highp vec4 qt_Vertex;
0201 attribute highp vec2 qt_MultiTexCoord0;
0202 varying highp vec2 qt_TexCoord0;
0203 uniform highp float startX;
0204 uniform highp float startY;
0205 uniform highp float targetX;
0206 uniform highp float targetY;
0207 uniform highp float scaleWidth;
0208 uniform highp float scaleHeight;
0209 uniform highp float progress;
0210 
0211 highp mat4 morph = mat4(1.0 + (scaleWidth - 1.0) * progress, 0.0, 0.0, startX*(1.0-progress) + targetX*progress,
0212                         0.0, 1.0 + (scaleHeight - 1.0) * progress, 0.0, startY*(1.0-progress) + targetY*progress,
0213                         0.0, 0.0, 1.0, 0.0,
0214                         0.0, 0.0, 0.0, 1.0);
0215 
0216 void main() {
0217     qt_TexCoord0 = qt_MultiTexCoord0;
0218     gl_Position = qt_Matrix * qt_Vertex * morph;
0219 }
0220         `
0221     }
0222 
0223     ShaderEffect {
0224         id: sourceEffect
0225         x: 0
0226         y: 0
0227         parent: heroAnimation.source.QQC2.Overlay.overlay
0228         width: heroAnimation.source.width
0229         height: heroAnimation.source.height
0230         visible: false
0231         property variant source: heroAnimation.source
0232         property real progress: 0
0233         property real startX: heroAnimation.source.Kirigami.ScenePosition.x / (applicationWindow().width / 2)
0234         property real startY: -heroAnimation.source.Kirigami.ScenePosition.y / (applicationWindow().height / 2)
0235 
0236         property real targetX: scaleWidth - 1 + (heroAnimation.destination.Kirigami.ScenePosition.x * 2) / applicationWindow().width
0237         property real targetY: 1-scaleHeight - (heroAnimation.destination.Kirigami.ScenePosition.y * 2) / applicationWindow().height
0238         property real scaleWidth: heroAnimation.destination.width/heroAnimation.source.width
0239         property real scaleHeight: heroAnimation.destination.height/heroAnimation.source.height
0240         vertexShader: __privateShaderSources.vertexShader
0241         fragmentShader: `
0242 varying highp vec2 qt_TexCoord0;
0243 uniform sampler2D source;
0244 uniform lowp float qt_Opacity;
0245 uniform lowp float progress;
0246 void main() {
0247     gl_FragColor = texture2D(source, qt_TexCoord0) * qt_Opacity * (1.0 - progress);
0248 }
0249         `
0250     }
0251 
0252     ShaderEffect {
0253         id: destinationEffect
0254         x: 0
0255         y: 0
0256         parent: heroAnimation.destination.QQC2.Overlay.overlay
0257         width: heroAnimation.destination.width
0258         height: heroAnimation.destination.height
0259         visible: false
0260         property variant source: heroAnimation.destination
0261         property real progress: sourceEffect.progress
0262         property real startX: heroAnimation.destination.Kirigami.ScenePosition.x / (applicationWindow().width / 2)
0263         property real startY: -heroAnimation.destination.Kirigami.ScenePosition.y / (applicationWindow().height / 2)
0264 
0265         property real targetX: scaleWidth - 1 + (heroAnimation.source.Kirigami.ScenePosition.x * 2) / applicationWindow().width
0266         property real targetY: 1-scaleHeight - (heroAnimation.source.Kirigami.ScenePosition.y * 2) / applicationWindow().height
0267         property real scaleWidth: heroAnimation.source.width/heroAnimation.destination.width
0268         property real scaleHeight: heroAnimation.source.height/heroAnimation.destination.height
0269 
0270         property variant maskSource: root.mask.item
0271 
0272         vertexShader: __privateShaderSources.vertexShader
0273         fragmentShader: `
0274 varying highp vec2 qt_TexCoord0;
0275 uniform sampler2D source;
0276 uniform sampler2D maskSource;
0277 uniform lowp float qt_Opacity;
0278 uniform lowp float progress;
0279 void main() {
0280     gl_FragColor = texture2D(source, qt_TexCoord0) * texture2D(maskSource, qt_TexCoord0).a * qt_Opacity *  (1.0 - progress);
0281 }
0282         `
0283     }
0284 }