11<template >
2- <div
3- id =" shutter"
4- :class =" {
5- 'absolute w-screen h-dvh bg-surface-950 transition-opacity duration-1000 ease-in-out top-0 left-0': true,
6- 'z-50 opacity-0 pointer-events-none': is_slideshow_active,
7- }"
8- ></div >
92 <div class =" absolute z-20 top-0 left-0 w-full flex h-full overflow-hidden bg-black" >
103 <PhotoHeader :photo =" props.photo" @toggle-slide-show =" emits('toggleSlideShow')" @go-back =" emits('goBack')" />
114 <div class =" w-0 flex-auto relative" >
12- <div
13- id =" imageview"
14- class =" absolute top-0 left-0 w-full h-full bg-black flex items-center justify-center overflow-hidden"
15- @click =" emits('rotateOverlay')"
16- ref =" swipe"
17- :class =" {
18- 'pt-14': imageViewMode === ImageViewMode.Pdf && !is_full_screen,
19- }"
20- >
21- <!-- This is a video file: put html5 player -->
22- <video
23- v-if =" imageViewMode == ImageViewMode.Video"
24- width =" auto"
25- height =" auto"
26- id =" image"
27- ref =" videoElement"
28- controls
29- class =" absolute m-auto w-auto h-auto"
30- :class =" is_full_screen || is_slideshow_active ? 'max-w-full max-h-full' : 'max-wh-full-56'"
31- autobuffer
32- :autoplay =" lycheeStore.can_autoplay"
33- >
34- <source :src =" props.photo.size_variants.original?.url ?? ''" />
35- Your browser does not support the video tag.
36- </video >
37- <!-- This is a raw file: put a place holder -->
38- <embed
39- v-if =" imageViewMode == ImageViewMode.Pdf"
40- id =" image"
41- alt =" pdf"
42- :src =" props.photo.size_variants.original?.url ?? ''"
43- type =" application/pdf"
44- frameBorder =" 0"
45- scrolling =" auto"
46- class =" absolute m-auto animate-zoomIn bg-contain bg-center bg-no-repeat"
47- height =" 90%"
48- width =" 100%"
49- />
50- <!-- This is a raw file: put a place holder -->
51- <img
52- v-if =" imageViewMode == ImageViewMode.Raw"
53- id =" image"
54- alt =" placeholder"
55- class =" absolute m-auto w-auto h-auto animate-zoomIn bg-contain bg-center bg-no-repeat"
56- :src =" getPlaceholderIcon()"
57- />
58- <!-- This is a normal image: medium or original -->
59- <img
60- v-if =" imageViewMode == ImageViewMode.Medium"
61- id =" image"
62- alt =" medium"
63- class =" absolute m-auto w-auto h-auto animate-zoomIn bg-contain bg-center bg-no-repeat"
64- :src =" props.photo.size_variants.medium?.url ?? ''"
65- :class =" is_full_screen || is_slideshow_active ? 'max-w-full max-h-full' : 'max-wh-full-56'"
66- :srcset =" srcSetMedium"
67- />
68- <img
69- v-if =" imageViewMode == ImageViewMode.Original"
70- id =" image"
71- alt =" big"
72- class =" absolute m-auto w-auto h-auto animate-zoomIn bg-contain bg-center bg-no-repeat"
73- :class =" is_full_screen || is_slideshow_active ? 'max-w-full max-h-full' : 'max-wh-full-56'"
74- :style =" style"
75- :src =" props.photo.size_variants.original?.url ?? ''"
76- />
77- <!-- This is a livephoto : medium -->
78- <div
79- v-if =" imageViewMode == ImageViewMode.LivePhotoMedium"
80- id =" livephoto"
81- data-live-photo
82- data-proactively-loads-video =" true"
83- :data-photo-src =" photo?.size_variants.medium?.url"
84- :data-video-src =" photo?.live_photo_url"
85- class =" absolute m-auto w-auto h-auto"
86- :class =" is_full_screen || is_slideshow_active ? 'max-w-full max-h-full' : 'max-wh-full-56'"
87- :style =" style"
88- ></div >
89- <!-- This is a livephoto : full -->
90- <div
91- v-if =" imageViewMode == ImageViewMode.LivePhotoOriginal"
92- id =" livephoto"
93- data-live-photo
94- data-proactively-loads-video =" true"
95- :data-photo-src =" photo?.size_variants.original?.url"
96- :data-video-src =" photo?.live_photo_url"
97- class =" absolute m-auto w-auto h-auto"
98- :class =" is_full_screen || is_slideshow_active ? 'max-w-full max-h-full' : 'max-wh-full-56'"
99- :style =" style"
100- ></div >
101-
102- <!-- <x-gallery.photo.overlay /> -->
5+ <div class =" animate-zoomIn w-full h-full" >
6+ <Transition :name =" props.transition" >
7+ <div
8+ :key =" photo.id"
9+ id =" imageview"
10+ class =" absolute top-0 left-0 w-full h-full flex items-center justify-center overflow-hidden"
11+ @click =" emits('rotateOverlay')"
12+ ref =" swipe"
13+ :class =" {
14+ 'pt-14': imageViewMode === ImageViewMode.Pdf && !is_full_screen,
15+ }"
16+ >
17+ <!-- This is a video file: put html5 player -->
18+ <video
19+ v-if =" imageViewMode == ImageViewMode.Video"
20+ width =" auto"
21+ height =" auto"
22+ id =" image"
23+ ref =" videoElement"
24+ controls
25+ class =" absolute m-auto w-auto h-auto"
26+ :class =" is_full_screen || is_slideshow_active ? 'max-w-full max-h-full' : 'max-wh-full-56'"
27+ autobuffer
28+ :autoplay =" lycheeStore.can_autoplay"
29+ >
30+ <source :src =" props.photo.size_variants.original?.url ?? ''" />
31+ Your browser does not support the video tag.
32+ </video >
33+ <!-- This is a raw file: put a place holder -->
34+ <embed
35+ v-if =" imageViewMode == ImageViewMode.Pdf"
36+ id =" image"
37+ alt =" pdf"
38+ :src =" props.photo.size_variants.original?.url ?? ''"
39+ type =" application/pdf"
40+ frameBorder =" 0"
41+ scrolling =" auto"
42+ class =" absolute m-auto bg-contain bg-center bg-no-repeat"
43+ height =" 90%"
44+ width =" 100%"
45+ />
46+ <!-- This is a raw file: put a place holder -->
47+ <img
48+ v-if =" imageViewMode == ImageViewMode.Raw"
49+ id =" image"
50+ alt =" placeholder"
51+ class =" absolute m-auto w-auto h-auto bg-contain bg-center bg-no-repeat"
52+ :src =" getPlaceholderIcon()"
53+ />
54+ <!-- This is a normal image: medium or original -->
55+ <img
56+ v-if =" imageViewMode == ImageViewMode.Medium"
57+ id =" image"
58+ alt =" medium"
59+ class =" absolute m-auto w-auto h-auto bg-contain bg-center bg-no-repeat"
60+ :src =" props.photo.size_variants.medium?.url ?? ''"
61+ :class =" is_full_screen || is_slideshow_active ? 'max-w-full max-h-full' : 'max-wh-full-56'"
62+ :srcset =" srcSetMedium"
63+ />
64+ <img
65+ v-if =" imageViewMode == ImageViewMode.Original"
66+ id =" image"
67+ alt =" big"
68+ class =" absolute m-auto w-auto h-auto bg-contain bg-center bg-no-repeat"
69+ :class =" is_full_screen || is_slideshow_active ? 'max-w-full max-h-full' : 'max-wh-full-56'"
70+ :style =" style"
71+ :src =" props.photo.size_variants.original?.url ?? ''"
72+ />
73+ <!-- This is a livephoto : medium -->
74+ <div
75+ v-if =" imageViewMode == ImageViewMode.LivePhotoMedium"
76+ id =" livephoto"
77+ data-live-photo
78+ data-proactively-loads-video =" true"
79+ :data-photo-src =" photo?.size_variants.medium?.url"
80+ :data-video-src =" photo?.live_photo_url"
81+ class =" absolute m-auto w-auto h-auto"
82+ :class =" is_full_screen || is_slideshow_active ? 'max-w-full max-h-full' : 'max-wh-full-56'"
83+ :style =" style"
84+ ></div >
85+ <!-- This is a livephoto : full -->
86+ <div
87+ v-if =" imageViewMode == ImageViewMode.LivePhotoOriginal"
88+ id =" livephoto"
89+ data-live-photo
90+ data-proactively-loads-video =" true"
91+ :data-photo-src =" photo?.size_variants.original?.url"
92+ :data-video-src =" photo?.live_photo_url"
93+ class =" absolute m-auto w-auto h-auto"
94+ :class =" is_full_screen || is_slideshow_active ? 'max-w-full max-h-full' : 'max-wh-full-56'"
95+ :style =" style"
96+ ></div >
97+
98+ <!-- <x-gallery.photo.overlay /> -->
99+ </div >
100+ </Transition >
103101 </div >
104102 <NextPrevious
105103 v-if =" photo.previous_photo_id !== null && !is_slideshow_active"
@@ -148,6 +146,7 @@ import { useSwipe, type UseSwipeDirection } from "@vueuse/core";
148146import { shouldIgnoreKeystroke } from " @/utils/keybindings-utils" ;
149147import { onUnmounted } from " vue" ;
150148import { useDebounceFn } from " @vueuse/core" ;
149+ import { Transition } from " vue" ;
151150
152151const swipe = ref <HTMLElement | null >(null );
153152const videoElement = ref <HTMLVideoElement | null >(null );
@@ -163,6 +162,7 @@ const props = defineProps<{
163162 photo: App .Http .Resources .Models .PhotoResource ;
164163 photos: App .Http .Resources .Models .PhotoResource [];
165164 isMapVisible: boolean ;
165+ transition: " slide-next" | " slide-previous" ;
166166}>();
167167
168168const photo = ref (props .photo );
@@ -235,3 +235,45 @@ watch(
235235 },
236236);
237237 </script >
238+
239+ <style lang="css">
240+ .slide-next-leave-active ,
241+ .slide-next-enter-active {
242+ transition :
243+ transform 0.5s cubic-bezier (0.165 , 0.84 , 0.44 , 1 ),
244+ opacity 0.2s cubic-bezier (0.445 , 0.05 , 0.55 , 0.95 );
245+ }
246+ .slide-next-enter-from {
247+ transform : translate (5% , 0 );
248+ opacity : 0 ;
249+ }
250+ .slide-next-enter-to ,
251+ .slide-next-leave-from {
252+ transform : translate (0 , 0 );
253+ opacity : 1 ;
254+ }
255+ .slide-next-leave-to {
256+ transform : translate (-5% , 0 );
257+ opacity : 0 ;
258+ }
259+
260+ .slide-previous-leave-active ,
261+ .slide-previous-enter-active {
262+ transition :
263+ transform 0.5s cubic-bezier (0.165 , 0.84 , 0.44 , 1 ),
264+ opacity 0.2s cubic-bezier (0.445 , 0.05 , 0.55 , 0.95 );
265+ }
266+ .slide-previous-enter-from {
267+ transform : translate (-5% , 0 );
268+ opacity : 0 ;
269+ }
270+ .slide-previous-enter-to ,
271+ .slide-previous-leave-from {
272+ transform : translate (0 , 0 );
273+ opacity : 1 ;
274+ }
275+ .slide-previous-leave-to {
276+ transform : translate (5% , 0 );
277+ opacity : 0 ;
278+ }
279+ </style >
0 commit comments