返回 slidev
SlidesShow.vue
根目录 / packages / client / internals / SlidesShow.vue
1 <script setup lang="ts">
2 import type { SlideRoute } from '@slidev/types'
3 import { recomputeAllPoppers } from 'floating-vue'
4 import { computed, shallowRef, TransitionGroup, watchEffect } from 'vue'
5 import { GlobalBottom, GlobalTop } from '#slidev/global-layers'
6 import { createFixedClicks } from '../composables/useClicks'
7 import { useNav } from '../composables/useNav'
8 import { usePreloadImages } from '../composables/usePreloadImages'
9 import { useViewTransition } from '../composables/useViewTransition'
10 import { CLICKS_MAX } from '../constants'
11 import { activeDragElement, disableTransition, hmrSkipTransition } from '../state'
12 import DragControl from './DragControl.vue'
13 import SlideWrapper from './SlideWrapper.vue'
14
15 defineProps<{
16 renderContext: 'slide' | 'presenter'
17 }>()
18
19 const {
20 currentSlideRoute,
21 currentTransition,
22 getPrimaryClicks,
23 prevRoute,
24 nextRoute,
25 slides,
26 isPrintMode,
27 isPrintWithClicks,
28 clicksDirection,
29 printRange,
30 } = useNav()
31
32 function preloadRoute(route: SlideRoute) {
33 if (route.meta.preload !== false) {
34 route.meta.__preloaded = true
35 route.load()
36 }
37 }
38 // preload current, prev and next slides
39 watchEffect(() => {
40 preloadRoute(currentSlideRoute.value)
41 preloadRoute(prevRoute.value)
42 preloadRoute(nextRoute.value)
43 })
44 // preload all slides after 3s
45 watchEffect((onCleanup) => {
46 const routes = slides.value
47 const timeout = setTimeout(() => {
48 routes.forEach(preloadRoute)
49 }, 3000)
50 onCleanup(() => clearTimeout(timeout))
51 })
52
53 // preload images for nearby slides
54 usePreloadImages(currentSlideRoute, prevRoute, nextRoute, slides)
55
56 const hasViewTransition = useViewTransition()
57
58 const DrawingLayer = shallowRef<any>()
59 if (__SLIDEV_FEATURE_DRAWINGS__ || __SLIDEV_FEATURE_DRAWINGS_PERSIST__)
60 import('./DrawingLayer.vue').then(v => DrawingLayer.value = v.default)
61
62 const loadedRoutes = computed(() => isPrintMode.value
63 ? printRange.value.map(no => slides.value[no - 1])
64 : slides.value.filter(r => r.meta?.__preloaded || r === currentSlideRoute.value),
65 )
66
67 function onAfterLeave() {
68 // After transition, we disable it so HMR won't trigger it again
69 // We will turn it back on `nav.go` so the normal navigation would still work
70 hmrSkipTransition.value = true
71 // recompute poppers after transition
72 recomputeAllPoppers()
73 }
74 </script>
75
76 <template>
77 <!-- Global Bottom -->
78 <GlobalBottom />
79
80 <!-- Slides -->
81 <component
82 :is="(hasViewTransition && !isPrintMode && !hmrSkipTransition && !disableTransition) ? 'div' : TransitionGroup"
83 v-bind="(hmrSkipTransition || disableTransition || isPrintMode) ? {} : currentTransition"
84 id="slideshow"
85 tag="div"
86 :class="{
87 'slidev-nav-go-forward': clicksDirection > 0,
88 'slidev-nav-go-backward': clicksDirection < 0,
89 }"
90 @after-leave="onAfterLeave"
91 >
92 <template v-for="route of loadedRoutes" :key="route.no">
93 <SlideWrapper
94 v-show="route === currentSlideRoute"
95 :clicks-context="isPrintMode && !isPrintWithClicks ? createFixedClicks(route, CLICKS_MAX) : getPrimaryClicks(route)"
96 :route="route"
97 :render-context="renderContext"
98 />
99 </template>
100 </component>
101
102 <DragControl v-if="activeDragElement" :data="activeDragElement" />
103
104 <!-- Global Top -->
105 <GlobalTop />
106
107 <template v-if="(__SLIDEV_FEATURE_DRAWINGS__ || __SLIDEV_FEATURE_DRAWINGS_PERSIST__) && DrawingLayer">
108 <DrawingLayer />
109 </template>
110 </template>
111
112 <style scoped>
113 #slideshow {
114 height: 100%;
115 }
116 </style>
117
117 lines Plain Text