on ebf4a8a help sign in
unity8/Components/CrossFadeImage.qml
151 lines 4.2 kB history raw
1/*
2 * Copyright (C) 2013 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
17import QtQuick 2.0
19Item {
20 property url source
22 /*
23 * true: fade out old image in parallel with fading in the new one.
24 * false: fade in new image above old one.
25 *
26 * The reason why this is required is that crossfading has the isse that in
27 * the middle of the animation, both images are only 50% opaque which make
28 * any background shine through. Not wanted for background images etc, but
29 * wanted for overlays.
30 */
31 property bool crossFade: true
33 /*
34 * true: the very first source url should be faded in already.
35 * false: the very first source url should just be shown without animation.
36 */
37 property bool fadeInFirst: true
39 readonly property size sourceSize: __currentImage.sourceSize
40 readonly property var status: __currentImage ? __currentImage.status : Image.Null
41 readonly property bool running: crossFadeImages.running || nextImageFadeIn.running
43 property Image __currentImage: image1
44 property Image __nextImage: image2
46 function swapImages() {
47 __currentImage.z = 0
48 __nextImage.z = 1
49 if (crossFade) {
50 crossFadeImages.start();
51 } else {
52 nextImageFadeIn.start();
53 }
55 var tmpImage = __currentImage
56 __currentImage = __nextImage
57 __nextImage = tmpImage
58 }
60 onSourceChanged: {
61 // On creation, the souce handler is called before image pointers are set.
62 if (__currentImage === null) {
63 __currentImage = image1;
64 __nextImage = image2;
65 }
67 crossFadeImages.stop();
68 nextImageFadeIn.stop();
70 // Don't fade in initial picture, only fade changes
71 if (__currentImage.source == "" && !fadeInFirst) {
72 __currentImage.source = source;
73 } else {
74 nextImageFadeIn.stop();
75 __nextImage.opacity = 0.0;
76 __nextImage.source = source;
78 // If case the image is still in QML's cache, status will be "Ready" immediately
79 if (__nextImage.status == Image.Ready || __nextImage.source == "") {
80 swapImages();
81 }
82 }
83 }
85 Connections {
86 target: __nextImage
87 onStatusChanged: {
88 if (__nextImage.status == Image.Ready || __nextImage.status == Image.Error) {
89 swapImages();
90 }
91 }
92 }
94 Image {
95 id: image1
96 anchors.fill: parent
97 cache: false
98 asynchronous: true
99 fillMode: Image.PreserveAspectCrop
100 z: 1
101 }
103 Image {
104 id: image2
105 anchors.fill: parent
106 cache: false
107 asynchronous: true
108 fillMode: Image.PreserveAspectCrop
109 z: 0
110 }
112 NumberAnimation {
113 id: nextImageFadeIn
114 target: __nextImage
115 property: "opacity"
116 duration: 400
117 to: 1.0
118 easing.type: Easing.InOutQuad
120 onRunningChanged: {
121 if (!running) {
122 __nextImage.source = "";
123 }
124 }
125 }
127 ParallelAnimation {
128 id: crossFadeImages
129 NumberAnimation {
130 target: __nextImage
131 property: "opacity"
132 duration: 400
133 to: 1.0
134 easing.type: Easing.InOutQuad
135 }
137 NumberAnimation {
138 target: __currentImage
139 property: "opacity"
140 duration: 400
141 to: 0
142 easing.type: Easing.InOutQuad
143 }
145 onRunningChanged: {
146 if (!running) {
147 __nextImage.source = "";
148 }
149 }
150 }