File tree Expand file tree Collapse file tree 2 files changed +91
-18
lines changed Expand file tree Collapse file tree 2 files changed +91
-18
lines changed Original file line number Diff line number Diff line change 3
3
<ul class =" list" :style =" { paddingBottom: `${aspectRatio}%` }" role =" button" @click =" next" >
4
4
<TransitionGroup name =" slide" >
5
5
<li v-for =" (stack, i) in stacks" :key =" stack.src" class =" item" :class =" `item-${i}`" >
6
- <figure class =" figure" >
7
- <img class =" img" :src =" stack.src" :alt =" stack.alt" >
8
- </figure >
6
+ <ImageStackItem :image =" stack" />
9
7
</li >
10
8
</TransitionGroup >
11
9
</ul >
38
36
import Vue , { PropOptions } from ' vue'
39
37
import IconChevronLeft from ' ./icons/IconChevronLeft.vue'
40
38
import IconChevronRight from ' ./icons/IconChevronRight.vue'
39
+ import ImageStackItem from ' ./ImageStackItem.vue'
41
40
42
41
interface Image {
43
42
src: string
@@ -53,7 +52,8 @@ interface Classes {
53
52
export default Vue .extend ({
54
53
components: {
55
54
IconChevronLeft ,
56
- IconChevronRight
55
+ IconChevronRight ,
56
+ ImageStackItem
57
57
},
58
58
59
59
props: {
@@ -218,8 +218,8 @@ export default Vue.extend({
218
218
transform : translate (0 , 0 ) scale (1 );
219
219
}
220
220
221
- .item-0 .figure { filter : blur (32 px ); }
222
- .item-1 .figure { filter : blur (16 px ); }
221
+ .item-0 >>> .figure { filter : blur (32 px ); }
222
+ .item-1 >>> .figure { filter : blur (16 px ); }
223
223
224
224
.item-0.slide-enter ,
225
225
.item-0.slide-leave-to ,
@@ -229,18 +229,6 @@ export default Vue.extend({
229
229
opacity : 0 ;
230
230
}
231
231
232
- .figure {
233
- filter : blur (0 );
234
- transition : filter 0.75 s ;
235
- }
236
-
237
- .img {
238
- width : 100 % ;
239
- height : 100 % ;
240
- border-radius : 8 px ;
241
- object-fit : cover;
242
- }
243
-
244
232
.control {
245
233
position : relative;
246
234
display : flex;
Original file line number Diff line number Diff line change
1
+ <template >
2
+ <div class =" ImageStackItem" >
3
+ <div class =" loader" :class =" { loaded }" >
4
+ <IconPreloaderDark class =" loader-icon" />
5
+ </div >
6
+
7
+ <figure class =" figure" >
8
+ <img class =" img" :src =" image.src" :alt =" image.alt" @load =" loaded = true" >
9
+ </figure >
10
+ </div >
11
+ </template >
12
+
13
+ <script lang="ts">
14
+ import Vue , { PropOptions } from ' vue'
15
+ import IconPreloaderDark from ' ./icons/IconPreloaderDark.vue'
16
+
17
+ interface Image {
18
+ src: string
19
+ alt: string
20
+ }
21
+
22
+ export default Vue .extend ({
23
+ components: {
24
+ IconPreloaderDark
25
+ },
26
+
27
+ props: {
28
+ image: { type: Object , required: true } as PropOptions <Image >
29
+ },
30
+
31
+ data () {
32
+ return {
33
+ loaded: false
34
+ }
35
+ },
36
+
37
+ mounted () {
38
+ // In case the image load event would not fire, we'll force displaying
39
+ // the image after 3 sec.
40
+ setTimeout (() => { this .loaded = true }, 3000 )
41
+ }
42
+ })
43
+ </script >
44
+
45
+ <style lang="postcss" scoped>
46
+ @import '@/assets/styles/variables' ;
47
+
48
+ .loader {
49
+ position : absolute;
50
+ top : 0 ;
51
+ right : 0 ;
52
+ bottom : 0 ;
53
+ left : 0 ;
54
+ z-index : 20 ;
55
+ background-color : var (--c-white );
56
+ transition : opacity 0.5 s ;
57
+ }
58
+
59
+ .loader.loaded {
60
+ opacity : 0 ;
61
+ }
62
+
63
+ .loader-icon {
64
+ position : absolute;
65
+ top : 50 % ;
66
+ left : 50 % ;
67
+ width : 48 px ;
68
+ height : 48 px ;
69
+ transform : translate (-50 % );
70
+ }
71
+
72
+ .figure {
73
+ position : relative;
74
+ z-index : 10 ;
75
+ filter : blur (0 );
76
+ transition : filter 0.75 s ;
77
+ }
78
+
79
+ .img {
80
+ width : 100 % ;
81
+ height : 100 % ;
82
+ border-radius : 8 px ;
83
+ object-fit : cover;
84
+ }
85
+ </style >
You can’t perform that action at this time.
0 commit comments